Hilo General - Dudas de Java

Khanser

#89 Tener la sesión abierta desde el principio hasta el final puede provocar que el servidor de bd te la cierre mientras que no le envías nada(dependiendo del server y de la config) de todas maneras, mientras no necesitas hacer consultas, no tiene sentido tener memoria ahí al tuntún.

Yo suelo abrir conexión por cada grupo lógico de consultas que puede ir en conjunto con una o varias transacciones dependiendo del caso. Abrir conexión para cada consulta puede ser contraproducente, piensa que por cada consulta habrá 2 mensajes que se manden al server por haber abierto y cerrado la sesión, así que bueno.. ya te puedes imaginar como se pondría la red para apps con muchas consultas XD. Además que abrir y cerrar sesión por cada consulta es perder el concepto de transacción y no podrás hacer rollbacks en caso de error.

2 respuestas
Tig

#89 Diría que depende del número de usuarios. Si la concurrencia es muy baja te puede interesar mantener la conexión abierta, pero supongo que esto te puede crear problemas cuando la concurrencia es alta. Abrir/cerrar conexión siempre conlleva un coste, eso es evidente.

Me suena que en php había algo que te ayudaba a mantener conexiones abiertas y reciclables de un usuario a otro, en su día lo toqué pero ahora lo tengo en los pies :)

hay gente que me da mil vueltas en este tema, a ver cual es su opinión (aunque esto no es una duda de java sino más genérica).

edit: #91 lo ha expresado mejor que yo. Hace tiempo que no toco nada web/sql :_(

1 respuesta
PiPePiTo

#91 #92 Muchas gracias por la respuesta a los dos :P

Ahora me viene otra duda.

Tengo un Thread en una clase que lo que viene siendo es un cronómetro (una clase visual) y que tiene un botón.

Cuando ese botón se pulsa el Thread se pausa y se abre otro frame que tiene una Progressbar con otro Thread.

Ahora bien, cierro el frame que creo ¿cómo puedo reanudar el primer Thread?

He intentado metiéndole el método cuando el frame hace el dispose pero obviamente como esa clase no es la que lleva el Thread está un tanto complicado...

1 respuesta
Khanser

#93 Como "pausas" el hilo en cuestion, con lógica o usando Thread.stop o Thread.suspend?

Si estás usando alguna de estas últimas no te lo recomiendo, en Java6 se marcaron estos métodos como deprecated porque no liberan los recursos que tienen apropiados, además que si usas el método stop, no puedes volver a reanudarlo. Lo que yo haría para 'pausarlo' es meterlo en un bucle en el que se durmiera en intervalos de 300 a 500 ms dependiendo de un parámetro.

Lo que yo haría (PauseThreadControl sería un objeto que me montaría yo)

public void run(){
    /*
    blablablal
    */
    while(isPaused()){ 
        Thread.sleep(500);
    }
    /*
    blablablal
    */
}
...
public boolean isPaused(){
    return PauseThreadControl.getInstance()
        .getState(Thread.getCurrentThread()).isPaused();
}

Como en el código que te he puesto arriba, puedes poner un control central que lleve el estado de los hilos que tengas en tu poder y este objeto PauseThreadControl debe controlar el acceso concurrente.

Además de esto me montaría los hilos para que pudieran recibir eventos de pausado y poder parar los procesos que se están llevando a cabo(para liberar recursos reservados y evitar deadlocks) guardando un contexto para seguir por donde se quedaron cuando se despausen.

2 respuestas
PiPePiTo

#94 me estoy empezando a enamorar de tus explicaciones x'DDD :P Muchas gracias... este tipo de cosas nos las tendrían que haber enseñado en el ciclo x'DDD

#95 estoy mirando, ahora mismo lo detengo con un interrupt (crono.interrupt(); sería en este caso)

2 respuestas
Khanser

#95 Vale, despues de ojear un poco más la api me he acordado que Thread tiene los métodos .wait() y el .notify(). Cuidao con el metodo .wait que puede lanzar una excepción, pero la llamada a .wait la haria desde un método del propio Thread tuyo por el tema que te he explicado antes de poder 'acabar' algo que esté haciendo si es que es lo que necesita.

1 respuesta
Ronso

Como si no pusiera nada ;)

14 días después
Lecherito

Buenas, estoy intentando hacer un sistema de módulos. Hay alguna manera de que si tienes un .jar, añadirlo una vez arrancado el programita y que haga X funciones del tipo onLoad() o onStart o algo por el estilo?

He estado buscando cosas sobre plugins y vi JSPF pero no llego a entenderlo del todo bien macho.

1 respuesta
elkaoD

#94 pausa por polling = mala idea. MUY MALA IDEA xD

#95 wait y notify son tus amigos.

EDIT: vale, veo que en #96 comentas wait y notify.

MTX_Anubis

#98 Mirate esto:

http://www.osgi.org/Main/HomePage
http://en.wikipedia.org/wiki/OSGi

Basicamente los jar tienen un activator que se declara en su manifest y cuando los instalas en la aplicacion se llama al start() del activator pues ya haces lo que quieras con el bundle registrando servicios que se pueden utilizar desde el resto de la aplicación.

1 respuesta
Lecherito

#100 No llego a entenderlo demasiado bien, he de crear una mini aplicación para que cargue todos los bundles, que son los .jar (plugins), y cada bundle tiene un start() que es lo que se inicia cada vez que arranca, no?

1 respuesta
MTX_Anubis

#101 La idea es algo así. Al princpio puede parecer complejo pero ya verás como luego añadir bundles y demás es coser y cantar, será como crear un nuevo proyecto y listo. Con eclipse por ejemplo, al crear un proyecto te deja hacerlo como un bundle directamente porque eclipse es puramente OSGi.

Lo suyo es utilizar ya alguna librería que te gestione toda la forma de instalar/desinstalar los bundles, por ejemplo, felix.

http://felix.apache.org/site/apache-felix-osgi-tutorial.html

Ahora mismo no puedo pero miraré a ver si esta semana tengo tiempo de pasarte un proyecto simple que registre un servicio, a partir de ahí es hacer siempre lo mismo. Probablemente, como lo hago no es la mejor manera ya que son bundles con dependencias pero como te vuelvas puristas la cosa se puede complica mucho sobre todo por la falta de información.

Aquí tienes un libro de OSGi para que vayas leyendo:
http://njbartlett.name/files/osgibook_preview_20091217.pdf

17 días después
Wasd

Buenas. Tengo una duda más bien genérica de Java y casi del resto de lenguajes.
Según me dicen los profesores, lo mejor es tenerlo TODO separado por métodos (incluso me han dicho que no superen las 9 - 12 lineas cada método).
Divide y vencerás, tiene su lógica, pero también pienso que puede que sea más lento, menos optimizado, al tener que estar haciendo constantes llamadas a métodos externos y clases.
Llevo tiempo aprendiendo pero todavía me faltan muchas cosas por asimilar, espero que me podáis aclarar esta en particular.

1 respuesta
BLZKZ

#103 sobre todo para reutilizar, o hacer cambios más adelante es mejor tener métodos/funciones menos densos, y por modularizar no vas a perder rendimiento, y más si hablamos de java que se pierde por todos lados.

Ellos tienen razón en eso, pero ojo eso de poner un "limite indicativo" pues no se yo, no lo veo demasiado claro, yo no voy contanto las líneas xD, eso si, no se me ocurre hacer un método de 200 o 300 a no ser que sea estrictamente necesario.

1 1 respuesta
Wasd

#104 ;) Gracias por la aclaración, realmente lo necesitaba y no me importa si alguien quiere alargar la explicación 400 líneas más, me lo leeré encantado.
Lo del límite de líneas me imagino que me lo dijeron simplemente para hacerme ver que no se deben hacer métodos muy largos.
Hay alguna diferencia notable entre tener una clase y 25724 métodos en ella y tener 25724 clases y un método en cada una?
El programa puede perder funcionalidad? Qué es mas adecuado?
Pongo extremos para que se entienda mejor la pregunta.

1 respuesta
zoeshadow

Lo que tienes que intentar siempre es seguir el diagrama de clases que hayas hecho, algunas clases por lo que sea, tendrán muchísimos métodos, y otras tendrán dos o tres.
Claro que para pequeños programas como los que hacemos en clase se hace aburrido tener que montar un diagrama de clases para cada uno.
Por mi experiencia, el hacer métodos mas cortos ayuda a que en un futuro puedas reutilizar el código, aparte que también hace el código mas legible, gracias a la navegabilidad de los IDE ( control + click ).

Wasd

Tengo una clase que contiene un método que crea un frame y le da la información básica (tamaño, titulo, setBounds, resizable, visible y exit_on_close).
Hay forma de dibujarle gráficos desde el método paint(Graphics g) estando este en otra clase?

1 respuesta
zoeshadow

#107 Prueba a crear un método en otra clase que pida por atributos un frame

public void dibujarFrame( Frame cuadro ){
    cuadro.paint();
    // o lo que quieras meterle
}

También puedes meterlo en el constructor de la otra clase o hacer la variable del frame static de manera que podrías acceder myClass.Frame

No se si eso responde a tu duda.

1 respuesta
B

#105: No te compliques con lo de los métodos y las clases. Cada clase tendrá los métodos que les correpondan. Una puede tener uno o dos y otra quince.

Wasd

#108 Gracias por tu ayuda, sin embargo no consigo que el paint me pinte en el frame de otra clase.
Cuelgo el código de ambas clases a ver si me podéis ayudar:

Objeto que contiene el JFrame
Objeto que contiene el paint(Graphics g)
Sergeon

Creo que es imprescindible que el la clase que contiene paint(Graphics g) herede de alguna clase gráfica de Java para que el JFrame pueda utilizar lo que pongas en el paint.

Por otro lado no entiendo bien porqué creas una clase que hereda de JFrame y luego le pones un JFrame jf con un método estático que le mande a ese método que se inicialice y recoja al objeto DefaultGraphics df: puedes hacerlo todo con un método window(DefaultGraphics) de HeliFrame que haga todo eso para sí mismo; no sé si me explico. En cualquier caso yo he hecho este código a partir del tuyo; en principio a mí me compila y hace lo que quiero que haga:

el Jframe
El JComponent/DefaultGraphics
la clase con main:

Es la primera vez que pego código en el foro así que si el formato sale horrible o no sale nada no quiero saber nada :D

1 mes después
Lecherito

Tengo una duda: Tengo un metodo tal que:

void asdf() {
 System.out.println("asdf");
 System.out.println("asdf");
 System.out.println("asdf");
 System.out.println("asdf");
}
void main() {
  asdf();
  System.out.println("hilado");
}

Cómo podría hacer un hilo de ese método para poder seguir con el programa mientras ese método se hace simultáneamente?

Quizá es algo raro de explicar xD

Así que en el main ejecutaría el metodo asdf(); en un hilo distinto y seguiría con el código imprimiendo la palabra "hilado".

Es más o menos lo que quiero, gracias!

1 respuesta
B

#112: http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html

1 mes después
C

La duda más tonta del mundo. Me da igual parecer un n00b, pero no lo veo xDDD:

Ahí va el código y luego la pregunta:

public class MyPancake implements Pancake {
	public static void main(String[] args) {
		List<String> x = new ArrayList<String>();
		x.add("3");
		x.add("7");
		x.add("5");
		List<String> y = new MyPancake().doStuff(x);
		y.add("1");
		System.out.println(x);
	}

public List<String> doStuff(List<String> z) {
	z.add("9");
	return z;
}
}

interface Pancake {
	List<String> doStuff(List<String> s);
}

La salida del programa es [3, 7, 5, 9, 1].

Pero mi duda es: ¿en qué momento la variable 'x' está apuntando a 'y'? ¿No se supone que en Java los pasos de parámetro son siempre por valor y no por referencia? Es que si hiciera x=y, tiene un pase. Pero no veo en qué parte de:

List<String> y = new MyPancake().doStuff(x);

se está haciendo un x=y.

Gracias.

P.D.: Me estoy preparando el OCJP y resuelvo preguntas más difíciles, pero esta gilipollez no lo veo, joder... xD

1 respuesta
elkaoD

#114 comorl? X no está apuntando a Y, es al revés :S

Tu main "desenrollado", sin llamar a doStuff:

x.add("3");
x.add("7");
x.add("5");
// Aquí viene la llamada a doStuff(x)
x.add("9");
List<String> y = x;
y.add("1");

Que eliminando la asignación superflua queda como:

x.add("3");
x.add("7");
x.add("5");
x.add("9");
x.add("1");

No sé qué es lo que no entiendes xD ¿Cuál de los dos pasos previos de "simplificación" es el que te parece raro?

PD: En Java, todo tipo que no sea basico (los que empiezan por minúscula, i.e. int, char, boolean, etc.) se pasa por referencia. SIEMPRE. Hay gente que te discutirá esto por cuestiones semánticas, pero me da igual.

1 respuesta
C

#115 Lo que no entiendo (debe ser tan obvio!) es dónde se hace el y = x.
Es decir, en:

List<String> y = new MyPancake().doStuff(x);

¿Se está creando un nuevo objeto de la clase MyPancake que apunta al mismo que está ejecutándose?

Digamos que en new MyPancake().doStuff(x) yo veo que se crea un nuevo objeto que se le asigna a la variable 'y'. Pero uno nuevo, no la referencia al objeto actual en ejecución.

Joder, tiene que ser una chorrada, pero no lo veo ostias xD

Edit: Vale joder! en tu PD está la clave. Es que no sabía que era así coño! xD
Ahora todo tiene sentido. Me he debido de saltar esa parte del libro ajajajaja. Gracias elkaod

De todas formas, vaya peligro. Lo suyo es que hubiera un indicador previo al objeto que se pasa. Pero claro, como no hay punteros...

Lo acabo de buscar por internet. Queda claro:

En Java el paso por parámetro es por valor, aunque los efectos son de paso por referencia cuando los argumentos son objetos. ¿cómo sucede eso? Pues es muy fácil, si una función tiene como argumento un tipo primitivo (int, float, etc...), en Java se realiza una copia para la función y cualquier cambio a dicho argumento no afecta a la variable original. Este paso de parámetros en Java está orientado a utilizar el valor de la variable para otros cálculos.

En el caso de los objetos es distinto. En realidad lo que sucede es que en Java siempre tenemos referencias a los objetos. Por eso al pasar a una función como argumento un objeto, pasamos la referencia al mismo, es decir, aunque se hace una copia para el paso por valor, como lo que se copia es una referencia, los cambios al objeto referenciado sí son visibles y afectan fuera de la función.

La única excepción es la clase String , cuyos objetos no son mutables. Cualquier modificación de un objeto String lleva aparejada la creación de una nueva instancia del objeto. Si deseamos el mismo comportamiento para el paso de parámetros del resto de objetos, tenemos que recurrir al objeto StringBuffer.

#117, has escrito mientras yo escribía mi propio Edit, ya lo entendí en #115 xD

1 respuesta
elkaoD

#116 sigo sin entender qué es lo que no ves. ¡VETE A DESCANSAR HOMBRE! xD

Para que lo veas bien, doStuff bien podría ser un método estático que haría lo mismo. No estás accediendo a miembros, ¿qué más dará a qué haga referencia?

List<String> y = StaticMyPancake.doStuff(x);

doStuff recibe un argumento y devuelve ese mismo argumento con "9" añadido. ¡No toca miembro alguno!

Aparte, no estás guardando un objeto MyPancake sino un List<String>, el que devuelve la llamada a (new MyPancake()).doStuff(x)


#116 En efecto, esa es la explicación a la que siempre hace alusión la gente. UNA MIERDA :P En Java el paso de hijos de Object es por referencia.

Por eso al pasar a una función como argumento un objeto, pasamos la referencia al mismo
Osea que dice que no está pasando por referencia, y tan pancho añade pasamos la referencia al mismo. ¡Qué calidad!

La única excepción es la clase String , cuyos objetos no son mutables. Cualquier modificación de un objeto String lleva aparejada la creación de una nueva instancia del objeto.
Esto ya es retarded total. Que el objeto sea inmutable hace que se convierta mágicamente en... ¿qué exactamente?

Ese texto lo he visto cientos de veces ya y nunca entiendo la argumentación que hace.

En realidad, el tío entendió mal que en Java el paso es por "valor de referencia", es decir, que es el valor de un puntero C de toda la vida, un int pusheado a la pila con un valor concreto... La historia es que en Java tú no puedes cambiar el valor del puntero (¡sólo el valor al que apuntan las variables locales que referencian los argumentos!) mientras que en C/C++ sí, de ahí que la gente se invente estas mamonadas de discusiones semánticas.

Te redirijo a http://stackoverflow.com/questions/40480/is-java-pass-by-reference donde en efecto, se enteran más (y explican mejor) que el menda este que siempre aparece en Google xD

I believe that much of the confusion on this issue has to do with the fact that different people have different definitions of the term "reference". People coming from a C++ background assume that "reference" must mean what it meant in C++, people from a C background assume "reference" must be the same as "pointer" in their language, and so on. Whether it's correct to say that Java passes by reference really depends on what's meant by "reference".

Más y mejor: http://stackoverflow.com/questions/8113781/what-exactly-does-pass-by-reference-mean


#116 De todas formas, vaya peligro. Lo suyo es que hubiera un indicador previo al objeto que se pasa. Pero claro, como no hay punteros...
¿Ein? ¿A qué te refieres con indicador previo?

Aún así, en Java si hay punteros. Otra cosa es que tú no lo veas, pero prueba a hacer:

String prueba = null;
prueba.charAt(0);

Obtendrás un bonito NullPointerException.

2 respuestas
C

#117 Sobre el indicador previo me refería a un lenguaje en el que programé (COOL) en el que se ponía el indicador VAR delante del parámetro para decir si lo pasabas por valor o por referencia. Es un lenguaje programado en C que no tenía punteros pero que permitía, como te comento, pasar parámetros de ambas formas (ya fueran de tipos primitivos o bien objetos).

1 respuesta
elkaoD

#118 es decir, como el ByRef y ByVal de VB. Eso son "qualifiers", cualificadores, a falta de un término mejor.

Para aclararte, piensa que en Java todo es como si viniese ByVal (de ahí lo de paso-de-referencia-por-valor), es decir, el comportamiento es el mismo que en VB sin cualificar.

Lo que falta para acabar con estas discusiones semánticas es terminología clara, porque en estas discusiones siempre se mezcla la implementación del paso y del objeto. La cuestión viene porque en C los pasos por referencia los hace por indirección (son básicamente lo mismo, con una sintaxis más tersa.)

paso-de-valor-por-valor (C sin punteros y los tipos unboxed en Java)
paso-de-referencia-por-valor (Java e indirección C, )
paso-de-
-por-referencia (operador & en C)

De hecho yo a Java le llamaría, para ser propios, paso por indirección (y le podría dar la razón en ese caso a los que dicen que NO es paso por referencia.)

B

Pues para mí es un paso por referencia, lo que pasas por valor es el puntero. No hay mucho que discutir :S

#121: Igual es que soy un paleto ignorante. Pero es tan sencillo como que lo que haces es pasar por valor el puntero.

Vamos, es como si en C pasas un int * a. Si haces *a=4, a valdrá cuatro después. Si haces a = NULL, te comes una mierda.

1 respuesta
Tema cerrado