Was ist der Unterschied zwischen dem Thread-Status WAIT und dem Thread-Status BLOCKED?
Die Thread.State-Dokumentation :
Verstopft
In diesem Status befindet sich ein Thread, der blockiert ist und auf eine Monitorsperre wartet.Warten
In diesem Status befindet sich ein Thread, der unendlich lange darauf wartet, dass ein anderer Thread eine bestimmte Aktion ausführt
erklärt mir den Unterschied nicht.
Ein Thread geht in den Wartezustand, sobald er wait()
für ein Objekt aufruft. Dies wird als Waiting State ..__ bezeichnet. Wenn ein Thread den Wartezustand erreicht, muss er warten, bis ein anderer Thread notify()
oder notifyAll()
am Objekt vorhanden ist.
Sobald dieser Thread benachrichtigt wurde, kann er nicht mehr ausgeführt werden. Es kann sein, dass auch andere Threads benachrichtigt werden (mithilfe von notifyAll()
) oder der erste Thread seine Arbeit noch nicht abgeschlossen hat. Er bleibt also blockiert, bis er seine Chance erhält. Dies wird als Blocked State bezeichnet.
Sobald andere Threads übrig sind und diese Thread-Chance besteht, wird der Status "Runable" (Runable) festgelegt. Danach kann die Arbeit basierend auf dem Threading-Mechanismus der JVM aufgenommen werden und der Status "Run" (Run) wird aktiviert.
Der Unterschied ist relativ einfach.
Im BLOCKED
-Status ist ein Thread im Begriff, einen synchronized
-Block einzugeben, es läuft jedoch ein anderer Thread innerhalb eines synchronized
-Blocks für dasselbe Objekt. Der erste Thread muss dann warten, bis der zweite Thread seinen Block beendet.
Im WAITING
-Status wartet ein Thread auf ein Signal von einem anderen Thread. Dies geschieht normalerweise durch Aufruf von Object.wait()
oder Thread.join()
. Der Thread bleibt dann in diesem Zustand, bis ein anderer Thread Object.notify()
aufruft oder stirbt.
Der wichtige Unterschied zwischen den Zuständen "blockiert" und "wait" ist die Auswirkung auf den Scheduler. Ein Thread im gesperrten Zustand ist Teil eines Wartesets, das um eine Sperre kämpft. Dieser Thread zählt immer noch als etwas, das der Scheduler warten muss, und wird möglicherweise in die Entscheidungen des Schedulers einbezogen, wie viel Zeit es für die Ausführung von Threads gibt.
Sobald sich ein Thread im Wartezustand befindet, wird die Belastung für das System minimiert, und der Scheduler muss sich nicht darum kümmern. Es wird inaktiv, bis es eine Benachrichtigung erhält. Abgesehen von der Tatsache, dass ein OS-Thread belegt ist, ist er völlig außer Betrieb.
Deshalb ist die Verwendung von notifyAll nicht ideal, da es eine Reihe von Threads verursacht, die zuvor glücklich inaktiv waren und das System nicht belastet, um geweckt zu werden. Die meisten von ihnen blockieren, bis sie die Sperre finden und den Zustand finden, in dem sie sich befinden Warten auf ist nicht wahr, und warten Sie ab. Es wäre wünschenswert, nur die Threads zu benachrichtigen, die die Chance haben, Fortschritte zu erzielen.
(Durch die Verwendung von ReentrantLock anstelle von intrinsischen Sperren können Sie mehrere Bedingungen für eine Sperre festlegen. So können Sie sicherstellen, dass der gemeldete Thread auf eine bestimmte Bedingung wartet, um den Benachrichtigungsfehler zu vermeiden, falls ein Thread benachrichtigt wird etwas, woran es nicht handeln kann.)
Vereinfachte Perspektive für die Interpretation von Thread-Dumps:
Blockiert: Ihr Thread befindet sich im laufenden Zustand des Threads und versucht, eine Objektsperre zu erhalten. Warten- Ihr Thread befindet sich im Wartezustand des Threads und wartet darauf, dass das Benachrichtigungssignal im Run-Zustand des Threads erscheint.
siehe dieses Beispiel:
demonstration der Threadzustände.
/*NEW- thread object created, but not started.
RUNNABLE- thread is executing.
BLOCKED- waiting for monitor after calling wait() method.
WAITING- when wait() if called & waiting for notify() to be called.
Also when join() is called.
TIMED_WAITING- when below methods are called:
Thread.sleep
Object.wait with timeout
Thread.join with timeout
TERMINATED- thread returned from run() method.*/
public class ThreadBlockingState{
public static void main(String[] args) throws InterruptedException {
Object obj= new Object();
Object obj2 = new Object();
Thread3 t3 = new Thread3(obj,obj2);
Thread.sleep(1000);
System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+
",when Wait() is called & waiting for notify() to be called.");
Thread4 t4 = new Thread4(obj,obj2);
Thread.sleep(3000);
System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+",After calling Wait() & waiting for monitor of obj2.");
System.out.println("nm:"+t4.getName()+",state:"+t4.getState().toString()+",when sleep() is called.");
}
}
class Thread3 extends Thread{
Object obj,obj2;
int cnt;
Thread3(Object obj,Object obj2){
this.obj = obj;
this.obj2 = obj2;
this.start();
}
@Override
public void run() {
super.run();
synchronized (obj) {
try {
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before Wait().");
obj.wait();
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After Wait().");
synchronized (obj2) {
cnt++;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Thread4 extends Thread{
Object obj,obj2;
Thread4(Object obj,Object obj2){
this.obj = obj;
this.obj2 = obj2;
this.start();
}
@Override
public void run() {
super.run();
synchronized (obj) {
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before notify().");
obj.notify();
System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After notify().");
}
synchronized (obj2) {
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}