style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Duda / Joins de Thread

Hola a tod@s. Estudiando este tutorial http://download.oracle.com/javase/tutorial/essential/concurrency/index.html, me atore en la sección de Joins con el siguiente problema:

Hice una clase que genera un numero entero aleatorio y mientras sea diferente a ( 2 ) otro especificado en un while genera un mensaje.

public class HelloRunnable implements Runnable {

    public void run() {
        int random = 0;
        while ((random = ((int) (Math.random() * 100))) != 2) {
            System.out.println(Thread.currentThread().getName() + " [" + random + "]");
        }
        System.out.println(Thread.currentThread().getName() + " {-- FIN --}");
    }
}

Bueno todo mono solo para probar un ejemplo de join. En el método main crea dos hilos y los inicia, antes de iniciar el hilo helloRunnable_2, se une el hilo helloRunnable_1 al padre, para que termine y muera, tantan...

public class Main {

    public static void main(String args[]) throws InterruptedException {
        Thread helloRunnable_1 = new Thread(new HelloRunnable());
        helloRunnable_1.setName("HelloRunnable-1");
        Thread helloRunnable_2 = new Thread(new HelloRunnable());
        helloRunnable_2.setName("HelloRunnable-2");

        helloRunnable_1.start();
        helloRunnable_1.join();

        helloRunnable_2.start();
    }
}

Esto genera algo como:

...
HelloRunnable-1 [15]
HelloRunnable-1 [12]
HelloRunnable-1 [0]
HelloRunnable-1 {-- FIN --}
...
HelloRunnable-2 [34]
HelloRunnable-2 [84]
HelloRunnable-2 {-- FIN --}

Y sí, jalo el ejemplo tan mini de join jejejeje.

La cosa que no entiendo es, sí yo cambio de lugar el join del método main como esto:

        ...
        helloRunnable_1.start();
        helloRunnable_2.start();

        helloRunnable_1.join();
        ...

Por qué genera algo como esto (como si no hubiera tomado en cuenta nunca el join):

HelloRunnable-2 [95]
HelloRunnable-2 [96]
HelloRunnable-2 [5]
HelloRunnable-1 [74]
HelloRunnable-2 [37]
HelloRunnable-2 [6]
HelloRunnable-2 {-- FIN --}
HelloRunnable-1 [22]
HelloRunnable-1 [91]
HelloRunnable-1 [42]
HelloRunnable-1 {-- FIN --}

O podrían recomendarme documentación en Internet y de libre sobre Hilos (Java).

Hice pruebas de tiempo con sleep o dejar el while(true){}, crear más hilos... bueno no se me ocurre porque sucede eso...

Muchas gracias : )

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

¿Que es lo que entendiste que

¿Que es lo que entendiste que debía de pasar?

Cuando usas join el hilo actual espera a que el hilo sobre el que lo invocas termine su ejecución.

Es por eso que en tu primer ejemplo ves:

1
1
1
1
1 fin

Por que no va a avanzar a la siguiente linea hasta que termine la ejecucion, que es, sobra decirlo, exactamente lo mismo que si lo hicieras con un solo hilo ( intenta llamar: new HelloRunnable().run() para que veas el efecto )

Cuando pones el join hasta abajo de los dos threads, ambos correran en "paralelo" y es por eso que te sale una salida entremezclada:

2
1
1
1
2
2
1

O sea que está funcionando como debe. La pregunta es: ¿Que es lo que habías entendido que iba a hacer? Quizá así te podría explicar porque no sale lo que esperas ( quizá lo que esperas tiene otro nombre ).

Imagen de ezamudio

join

El método join causa que el Thread desde donde invocaste ese método, se bloquee hasta que el thread invocado termine. En tu ejemplo, cuando invocas helloRunnable_1.join() lo que causas es que el thread principal (que no hace nada realmente) se bloquee hasta que el thread helloRunnable_1 termine su ejecución.

O qué, pensabas que se iba a unir con el hilo helloRunnable_2? Cómo sería eso posible, si helloRunnable_1 no sabe de la existencia de helloRunnable_2?

Imagen de rodrigo salado anaya

Duda / Joins de Thread: segun yo...

Según yo se preparan los dos hilos, se ponen en espera de su turno para CPU, lo toman, luego empieza el hilo-1, luegito el hilo-2, sacaría algo como

1
1
2
1
2

Hasta que llegue el join y solo salga

1
1
2
1
2
.....
1
1
1
1
1 fin
...
2
2
2
2 fin
// termina

En resumen, tendría que terminar primero el hilo-1, pero creoooooo jejeje que eso se resuelve con una sincronizada... pero esa duda me la quedo para otra entrada : ) y sip ya entendí...

Según yo: Cuando inicia el hilo-1 y hilo-2, y nunca le digo al hilo-2 que se detenga a causa del hilo-1. Pues síp Oscar correrán en paralelo : ), gracias por la explicación me sirvió mucho a entender una ligera diferencia : )

Imagen de rodrigo salado anaya

join: segun yo...

Si @Ezamudio ya entendí como va esto del join, he usado esto antes en varias ocasiones pero nunca sin entender los por qué claramente. Y pretendo entender lo mas que pueda del tema. Me podrías pasa la liga del material del curso que diste a la comunidad y otras???

Gracias por la explicación :) bye...

Segun te entiendo, lo que tu

Segun te entiendo, lo que tu esperabas es que: "Corriera el hilo 1 y hasta que terminara se ejecutara el hilo 2"?

Sucede que ( y esto no es muy claro ) en realidad tu tienes tres hilos ahí.

1.- El hilo principal que esta corriendo en el método main
y
2 y 3 , pues tus dos thread creados.

Entonces cuando dices: uno.join(); en realidad es el hilo main el que está esperando a que el thread "uno" termine. Y hasta entonces va a ejecutar la siguiente linea ( donde se inicia el hilo dos )

Si lo que quieres es que el hilo 2 se detenga hasta que el 1 termine, lo que podrías hacer es llamar join pero dentro del hilo que va a a esperar

Algo como:

import java.util.Random;
import static java.lang.System.out;
//
class A implements Runnable {

    Thread other; // el hilo a esperar
    public A(){} // constructor sin parametros ( new A() )
    public A( Thread t ) {   // constructor que recibe otro thread
        this.other = t;
    }
    public void run() {

        Random random = new Random(); //sacar numeros aleatorios de aqui
        int r = 0;
        int t = 10;

        while( (r = random.nextInt(100)) != 2 ) {  // mientras no sea 2

            out.println( this + " " + r ); // imprimelo

            // si ya corrio 10 veces y su "otro" hilo esta vivo
            if( other != null && t-- < 0 && other.isAlive() ) try  {  
                out.println( this + " esperando ");// lo espera
                other.join();
            } catch( InterruptedException ie ) {}
        }
        out.println( this + " fin");
    }
    public String toString() {
        return Thread.currentThread().getName();
    }
    // prueba
    public static void main( String ... args ) throws InterruptedException {
        Thread uno = new Thread( new A() );
        Thread dos = new Thread( new A(uno) );
        dos.start();
        uno.start();
        out.println( "fin del codigo" );
    }
}

Lo de sincronizar se usa cuando estás compartiendo datos, en este ejemplo no estás compartiendo datos, y los métodos clave ahí son wait y notifyAll ( extrañamente no de la clase java.lang.Thread, sino de la clase java.lang.Object ) sucede que en Java cada objeto puede ser un "lock" un candado.

También están las nuevas utilirias agregadas en Java 5, pero para serte sincero, jamás me he dado tiempo de aprenderlas.

Revisalas y mira si te sirven. Cuando llegues a la parte de compartir datos te pongo un ejemplo de wait y notifyAll

Ahi te va la salida del código:

fin del codigo
Thread-1 3
Thread-0 57
Thread-1 71
Thread-0 86
Thread-1 92
Thread-1 10
Thread-1 74
Thread-1 74
Thread-1 5
Thread-1 34
Thread-1 30
Thread-0 39
Thread-0 21
Thread-1 51
Thread-0 16
Thread-1 46
Thread-0 49
Thread-0 4
Thread-1 30
Thread-0 52
Thread-1 esperando
Thread-0 89
Thread-0 63
Thread-0 82
Thread-0 54
Thread-0 46
Thread-0 84
Thread-0 37
Thread-0 51
Thread-0 23
Thread-0 13
Thread-0 41
Thread-0 8
Thread-0 98
Thread-0 4
Thread-0 17
Thread-0 70
Thread-0 76
Thread-0 55
Thread-0 66
Thread-0 54
Thread-0 13
Thread-0 22
Thread-0 60
Thread-0 63
Thread-0 83
Thread-0 48
Thread-0 11
Thread-0 18
Thread-0 78
Thread-0 34
Thread-0 66
Thread-0 58
Thread-0 58
Thread-0 58
Thread-0 57
Thread-0 75
Thread-0 15
Thread-0 fin
Thread-1 98
Thread-1 37
Thread-1 16
Thread-1 45
Thread-1 46
Thread-1 81
Thread-1 51
Thread-1 85
Thread-1 93
Thread-1 63
Thread-1 40
Thread-1 7
Thread-1 57
Thread-1 83
Thread-1 60
Thread-1 58
Thread-1 75
Thread-1 12
Thread-1 47
Thread-1 29
Thread-1 76
Thread-1 97
Thread-1 54
Thread-1 77
Thread-1 41
Thread-1 91
Thread-1 48
Thread-1 64
Thread-1 75
Thread-1 79
Thread-1 19
Thread-1 36
Thread-1 63
Thread-1 16
Thread-1 23
Thread-1 7
Thread-1 68
Thread-1 76
Thread-1 9
Thread-1 9
Thread-1 35
Thread-1 5
Thread-1 98
Thread-1 52
Thread-1 0
Thread-1 95
Thread-1 87
Thread-1 12
Thread-1 74
Thread-1 95
Thread-1 81
Thread-1 24
Thread-1 85
Thread-1 55
Thread-1 42
Thread-1 43
Thread-1 9
Thread-1 75
Thread-1 10
Thread-1 64
Thread-1 8
Thread-1 28
Thread-1 45
Thread-1 10
Thread-1 61
Thread-1 91
Thread-1 41
Thread-1 24
Thread-1 36
Thread-1 67
Thread-1 40
Thread-1 46
Thread-1 90
Thread-1 16
Thread-1 45
Thread-1 0
Thread-1 57
Thread-1 92
Thread-1 0
Thread-1 88
Thread-1 84
Thread-1 52
Thread-1 57
Thread-1 51
Thread-1 81
Thread-1 78
Thread-1 73
Thread-1 5
Thread-1 37
Thread-1 35
Thread-1 84
Thread-1 50
Thread-1 82
Thread-1 52
Thread-1 82
Thread-1 20
Thread-1 20
Thread-1 75
Thread-1 61
Thread-1 76
Thread-1 93
Thread-1 28
Thread-1 8
Thread-1 21
Thread-1 47
Thread-1 85
Thread-1 fin
Imagen de rodrigo salado anaya

Gracias por el tip...

Excelente Oscar, gracias por el tip. Y sí, cuando llegue a el tema de Synchronization, ya preguntare más dudas :D.. A y también gracias por: random.nextInt(100). : )

Imagen de ezamudio

material

Imagen de rodrigo salado anaya

Material PCJ 9....

Gracias @Ezamudio, Solo recordaba la liga al zip. Esta super, le dedicare un rato para estudiarlo : )

EDIT: A no ma, el material esta fregon... y con bonus y toda la onda :D...

Imagen de rodrigo salado anaya

Ejemplo de Join

Dejo un muy sencillo ejemplo de Join, ya sin mi duda, por si alguien lo necesita. De poco sirve a enriquecer este hilo en el foro, pero tiene unas ligeras diferencias a los demás ejemplos, espero le ayuda a alguien.

import static java.lang.System.out;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Contador implements Runnable {

    private Thread t;

    public Contador() {
        t = new Thread(this);
        t.start();
    }

    public void run() {
        int i = 0;
        while (i < 16) {
            out.println(getThreadName() + "_" + i++);
        }
    }

    public void setJoin() {
        try {
            t.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(Contador.class.getName()).log(Level.SEVERE, "ERROR_JOIN", ex);
        }
    }

    private String getThreadName() {
        return Thread.currentThread().getName();
    }
}

public class Main {

    public static void main(String... args) {
        Contador contador_1 = new Contador();
        Contador contador_2 = new Contador();

        contador_1.setJoin();
        contador_2.setJoin();

        Contador contador_3 = new Contador();
    }
}

run:
Thread-1_0
Thread-1_1
Thread-1_2
Thread-1_3
Thread-0_0
Thread-1_4
Thread-0_1
Thread-1_5
Thread-1_6
Thread-1_7
Thread-1_8
Thread-1_9
Thread-1_10
Thread-1_11
Thread-1_12
Thread-1_13
Thread-1_14
Thread-1_15
Thread-0_2
Thread-0_3
Thread-0_4
Thread-0_5
Thread-0_6
Thread-0_7
Thread-0_8
Thread-0_9
Thread-0_10
Thread-0_11
Thread-0_12
Thread-0_13
Thread-0_14
Thread-0_15
Thread-2_0
Thread-2_1
Thread-2_2
Thread-2_3
Thread-2_4
Thread-2_5
Thread-2_6
Thread-2_7
Thread-2_8
Thread-2_9
Thread-2_10
Thread-2_11
Thread-2_12
Thread-2_13
Thread-2_14
Thread-2_15

Se podría esperar que se preparen los dos primeros threads, que tomen su lugar en CPU, luego solo se ejecute hasta que finalice el thread-0 y el thread-1 y por ultimo se ejecuta el thread-2.

Si vemos la salida no concuerda y pues con aumentar el valor del contador de 16 a 100 o un poco más y se verán los cambios, es por lo rápido del proceso.

Y el por qué inicia el hilo-1 y no el hilo-0? Es por que le gano en la competencia del CPU : ).
Bye : ).

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">