2009-07-30 7 views
1

Ich habe einen Thread, und ich brauche für das Ergebnis warten, wie folgt aus:Java Wait-For-Thread Frage

t1.start(); 
while (variableModifiedByMyThread == null) { 
    /* do nothing */ 
} 
// "t1" set the value of "variableModifiedByMyThread" 

Der obige Code funktioniert, aber nicht eine sehr schöne Lösung ...

Funktioniert dieser Code (wartet er auf den Thread "t1")?

t1.start(); 
try { 
    t1.join(); 
} catch (InterruptedException e) { 
    e.printStackTrace(); 
} 
// "t1" thread finished 
+2

Ihr erstes Codebeispiel ist hier nicht Thread-sicher. Es gibt keine Garantie dafür, dass der Hauptthread die Änderung an der Variable 'variableModifiedByMyThread' ohne Sperren/Synchronisation sieht. Dein Haupt-Thread könnte sich für immer drehen. – Jon

Antwort

4

Ersterer wartet auf das Setzen einer Variable, letzterer wartet auf den Thread. Wenn die Variable gerade eingestellt ist, bevor der Faden stirbt gibt es kaum einen Unterschied, außer:

  • Der ehemalige „Spins“ - der wartenden Thread etwas (Überprüfung der Variable) die ganze Zeit tut - sehr verschwenderisch!
  • Letzteres kann von einem anderen Thread unterbrochen werden.
+0

Ihre Antwort ist viel klarer als meine ist. +1 :) – aperkins

1

Was Ihr zweiter Code tut, ist t1, und warten Sie, bis er stirbt. Sobald t1 stirbt, wird es wieder starten. Siehe die javadoc für diese Methode.

1

Ja, außer dass Sie keine CPU-Zyklen verschwenden, indem Sie die Variable bei jeder Gelegenheit überprüfen. Dies ist ein viel besserer Weg, es zu tun.

Dies setzt voraus, dass die Variable nur geändert wird, wenn t1 beendet ist. Wenn t1 die Variable ändern und am Leben bleiben soll, wird dies nicht funktionieren.

Übrigens sollten Sie niemals einfach in einer solchen Schleife warten. Sie sollten zumindest innerhalb der Schleife Thread.yield() anrufen; Andernfalls können Sie möglicherweise viele Male eine Schleife erstellen, bevor Sie einen anderen Thread ausführen lassen.

Edit: Eigentlich kommen, daran zu denken, ein Ein-Element BlockingQueue ist wahrscheinlich das, was Sie wirklich wollen. Das klingt nach einem Produzenten-Konsumenten-Problem (vor allem, wenn Sie es mehr als einmal tun), und BlockingQueue ist für genau diese Art von Ding gebaut.

0
public class Test{ 
    private final Object lock = new Object(); 
    private Object var = null; 

    public void starThreadAndWaitForOutput(){ 
    Thread t1 = new Thread(new Runnable(){ 
     public void run(){ 
     synchronized(lock){ 
      var=new Object(); 
      lock.notify(); 
     } 
     } 
    }).start(); 

    synchronized(lock){ 
     while(var==null) 
     lock.wait(); 
    } 

    System.out.println("We have the var and thread 1 is still going!"); 
    } 
} 
+1

Dies ist nicht ganz richtig, Sie sollten vor unerwünschten Wake-ups schützen. (Informationen dazu finden Sie in der java.lang.Object.wait javadoc). Das Ergebnis ist, sollten Sie sagen: synchronisiert (Sperre) { while (var == null) { Sperre.warten(); } } – daveb

+0

Sie haben Recht! Ich machte die vorgeschlagene Lösung. – Charlie

4

Betrachten Future s. Die Idee ist, dass Sie einige Berechnungen haben, die "irgendwann in der Zukunft" abgeschlossen werden, und Sie können dann überprüfen, ob es abgeschlossen ist, oder darauf warten.

Vom javadoc:

FutureTask<String> future = 
    new FutureTask<String>(new Callable<String>() { 
    public String call() { 
     return searcher.search(target); 
    }}); 
executor.execute(future); 
+1

Upvote, aber mit der zusätzlichen Notiz, dass Sie es nicht einmal in eine FutureTask wickeln müssen. Senden Sie es einfach an einen ExecutorService – Tim

0

könnten Sie verwenden t1.yield() den Faden solange Sie pausieren die Bedingung gilt.