2011-01-13 5 views
1

Ich bin auf der Suche nach einer sehr einfachen Möglichkeit, mit einem Thread in Java zu kommunizieren. Betrachte das folgende Beispiel:Einfache Kommunikation mit einem Java-Thread

Ich muss nur wissen, ob doStuff() eine Null zurückgegeben hat oder nicht. Natürlich ist das in Java nicht erlaubt, aber wie kann ich es richtig implementieren? Es scheint, dass ich eine Art von Objekt brauche, das von SimpleThread geschrieben und vom Hauptthread gelesen werden kann. Was ist das fehlende Stück?

Antwort

4

Ein Beispiel unter Verwendung eines AtomicBoolean:

final AtomicBoolean pass = new AtomicBoolean(false); //making this final means we can access it in the anonymous Thread instance 
Thread simpleThread=new Thread(){ 
    public void run(){ 
    x=doStuff(); 
    if (x==0) pass.set(true); 
    } 
} 
simpleThread.start(); 
... 
pass.get(); //of course, this could return false simply because the newly spawned thread has not completed execution yet 
+0

Genau das habe ich gesucht. Es ist so einfach.AtomicBoolean hat mich umgehauen! – User1

+0

Ich verstehe die Verwendung von 'AtomicBoolean' in diesem Beispiel nicht vollständig. Dieses Beispiel basiert nicht auf der Semantik "Vergleichen und Tauschen", die meines Wissens die Hauptmotivation für die Verwendung von Atomics ist. Die Verwendung eines traditionellen flüchtigen booleschen Werts sollte äquivalent sein. – bluenote10

+0

@ bluenote10 Das Beispiel verwendet 'AtomicBoolean' eher als einfacher boolescher Halter. Ein flüchtiger boolescher Wert ist hier nicht möglich, da alle Deklarationen lokaler Geltungsbereich sind und in einer anonymen inneren Klasse nur auf ein lokales Finale zugegriffen werden kann. –

2

Sie benötigen ein gemeinsames Objekt, das die beiden Threads sehen können. Das Objekt muss veränderbar sein. Das heißt, Sie können keine Primitiven oder grundlegende Objekttypen wie String, Integer, Boolean usw. verwenden, da sie unveränderlich sind.

Sie müssen auch Thread-Synchronisierung verstehen und verwenden.

Hier ist ein Beispiel unter Verwendung einer Liste:

List mylist = new ArrayList(); 

in-thread 
{ 
    synchronized(mylist) 
    { 
     mylist.add(_something_); 
    } 
} 

in-another-thread 
{ 
    synchronized(mylist) 
    { 
     mylist.get(0); // do something with result; 
    } 
} 
+0

auch in die Atom Klassen aussehen möchten: http://download.oracle.com/javase/6/docs/api/java/util /concurrent/atomic/package-summary.html – Jeremy

+0

ohne Zweifel der Weg zu gehen, um das Ergebnis einer erzeugten Berechnung ist "Future" (siehe @jon Skeet) – mtraut

+1

wahr, re Future, aber es gibt keine Magie in Future/Callable/ExecutorService. Dies sind nur Dienstprogramme zum Durchführen der obigen grundlegenden Kommunikation zwischen Threads. Es ist für jeden guten Java-Entwickler hilfreich, Java-Threading-Primitive zu kennen, auch wenn er Utilities verwendet, die diese Konzepte etwas verbergen. –

8

Möglicherweise möchten Sie Future<T> verwenden. Anstatt einen neuen Thread direkt auf diese Weise zu starten, würden Sie wahrscheinlich eine ExecutorService verwenden und eine Callable<T> übergeben. Das würde eine Future<T> für Sie zurückgeben.

Sie könnten dann die Future<T> (aus dem ursprünglichen Thread) jederzeit fragen, ob es bereits beendet hat, oder einfach nur blockieren, bis es fertig (optional mit einem Timeout) hat.

Sie können das Äquivalent manuell mit einer gemeinsamen Variablen tun, aber persönlich denke ich, Ansatz ist sauberer in dem Fall, wenn Sie effektiv einen einzigen (möglicherweise komplexen) Wert auf einem anderen Thread berechnen. Wenn Sie regelmäßig mit dem Thread kommunizieren müssen (z. B. um mehr Arbeit zu leisten oder den Fortschritt zu sehen), dann ist das natürlich nicht angemessen.

0

Um @ Jons Vorschlag zu veranschaulichen.

ExecutorService executor = ... 

Future<Integer> result = executor.submit(new Callable<Integer>() { 
    public Integer call() { 
     return doStuff(); 
    } 
}); 

// later. 
Integer x = result.get(); 
boolean pass = x==0; 
Verwandte Themen