2011-08-12 17 views
5

Me wa no estar seguro de que alguna pieza de mi código en el hilo principal se ejecutará después de algún trozo de código que se ejecuta en el canto subproceso secundario. Aquí es lo que tengo:¿Manera más fácil de sincronizar 2 hilos en Java?

final Object lock = new Object(); 
    final Thread t = new Thread(new Runnable() { 
     public void run() { 
      synchronized(lock) { 
       System.out.println("qwerty"); 
       lock.notify(); 
      } 
     } 
    }); 

    synchronized(lock) { 
     t.start(); 
     lock.wait(); 
    } 

    System.out.println("absolutely sure, qwerty is above"); 
  1. ¿Es la solución correcta?
  2. Cualquier manera más cortos para hacer lo mismo?

Respuesta

5

Suponiendo que el hilo principal necesita para iniciar el procesamiento de la rosca secundaria, un Exchanger sería la solución más simple.

Si el hilo secundario es independiente, entonces algún tipo de BlockingQueue sería apropiado.


Un ejemplo que utiliza el Intercambiador (con el manejo de excepciones adecuado). El único Intercambiador podría ser sustituido por dos colas.

public static void main(String[] argv) 
throws Exception 
{ 
    final Exchanger<String> exchanger = new Exchanger<String>(); 
    new Thread(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      try 
      { 
       String s = exchanger.exchange(""); 
       System.out.println(s); 
       exchanger.exchange("this came from subthread"); 
      } 
      catch (InterruptedException ex) 
      { 
       System.out.println("interrupted while waiting for message"); 
      } 
     } 
    }).start(); 

    exchanger.exchange("this came from main thread"); 
    String s = exchanger.exchange(""); 
    System.out.println(s); 
} 
+1

La gente tiene que dar razones para la downvote –

+0

@Jeffrey - gracias. Tomé los enlaces que Google me dio, sin verificar la versión de JDK. – parsifal

+0

@John: hay motivos por los cuales hay muchos códigos multihebra rotos. IMO, el más grande es que la gente no piensa en cómo comunicarse entre hilos. – parsifal

12

Cosas como notificar() y wait() son muy primitivas de sincronización de bajo nivel.

Debe usar abstracciones de nivel superior siempre que sea posible, como en este caso, por ejemplo, un CountDownLatch.

El siguiente es sólo un ejemplo que servirán para iniciar (por ejemplo, no se tienen en cuenta las cuestiones de tiempo de espera aquí):

final CountDownLatch latch = new CountDownLatch(1); 
    final Thread t = new Thread(new Runnable() { 
     public void run() { 
      System.out.println("qwerty"); 
      latch.countDown(); 
     } 
    }); 

    t.start(); 
    latch.await(); 

    System.out.println("absolutely sure, qwerty as been printed"); 

de bajo nivel cosas como esperan y notificar son Realmente solo idiosincrasia Java de bajo nivel con la que no debería preocuparse (a menos que esté escribiendo API de concurrencia).

Además, sugiero leer el increíble libro: Java Concurrency In Practice.

-1
final Thread t = new Thread(new Runnable() { 
    public void run() { 
     System.out.println("qwerty"); 
    } 
}); 

t.start(); 
t.join(); 

System.out.println("absolutely sure, qwerty is above"); 
+0

Acabo de ver que mientras resuelve el ejemplo primitivo anterior, no hace lo que la pregunta especifica si el subhebra debería hacer algo más ... – DoubleMalt

-3

La mejor solución para el código que has dado es:

System.out.println("qwerty"); 
System.out.println("absolutely sure, qwerty is above"); 

No utilice roscado cuando no lo necesita.

Pero si sabes lo que estás haciendo con el hilo, entonces la solución de @ DoubleMalt es el camino a seguir (t.join()).

te había también, probablemente, les resulta digno de la lectura http://download.oracle.com/javase/tutorial/essential/concurrency/

Cuestiones relacionadas