ความแตกต่างระหว่างสถานะเธรด WAIT และสถานะเธรดถูกบล็อกคืออะไร?
ถูกบล็อก
เธรดที่ถูกบล็อกเพื่อรอการล็อกจอภาพอยู่ในสถานะนี้กำลังรอ
เธรดที่กำลังรอเธรดอื่นอย่างไม่มีกำหนดเพื่อดำเนินการเฉพาะอยู่ในสถานะนี้
ไม่ได้อธิบายความแตกต่างให้ฉัน
ความแตกต่างระหว่างสถานะเธรด WAIT และสถานะเธรดถูกบล็อกคืออะไร?
ถูกบล็อก
เธรดที่ถูกบล็อกเพื่อรอการล็อกจอภาพอยู่ในสถานะนี้กำลังรอ
เธรดที่กำลังรอเธรดอื่นอย่างไม่มีกำหนดเพื่อดำเนินการเฉพาะอยู่ในสถานะนี้
ไม่ได้อธิบายความแตกต่างให้ฉัน
คำตอบ:
เธรดจะเข้าสู่สถานะรอเมื่อเรียกwait()
ใช้อ็อบเจ็กต์ เรียกว่าสถานะรอ เมื่อเธรดถึงสถานะรอเธรดจะต้องรอจนกว่าจะมีการเรียกเธรดอื่น ๆnotify()
หรือnotifyAll()
บนอ็อบเจ็กต์
เมื่อเธรดนี้ได้รับแจ้งแล้วจะไม่สามารถรันได้ อาจเป็นไปได้ว่าเธรดอื่น ๆ ได้รับการแจ้งเตือนด้วย (โดยใช้notifyAll()
) หรือเธรดแรกยังทำงานไม่เสร็จดังนั้นจึงยังคงถูกบล็อกจนกว่าจะได้รับโอกาส สิ่งนี้เรียกว่าสถานะที่ถูกบล็อก สถานะถูกปิดกั้นจะเกิดขึ้นเมื่อใดก็ตามที่เธรดพยายามที่จะได้รับการล็อกบนอ็อบเจ็กต์และเธรดอื่น ๆ บางเธรดกำลังล็อคอยู่แล้ว
เมื่อเธรดอื่น ๆ ออกไปและโอกาสของเธรดนี้มันจะย้ายไปยังสถานะ Runnable หลังจากนั้นจึงมีสิทธิ์รับงานตามกลไกการทำงานของเธรด JVM และย้ายเพื่อรันสถานะ
ความแตกต่างค่อนข้างง่าย
ในBLOCKED
สถานะเธรดกำลังจะเข้าสู่synchronized
บล็อก แต่มีเธรดอื่นกำลังทำงานอยู่ภายในsynchronized
บล็อกบนอ็อบเจ็กต์เดียวกัน จากนั้นเธรดแรกจะต้องรอให้เธรดที่สองออกจากบล็อก
ในWAITING
สถานะเธรดกำลังรอสัญญาณจากเธรดอื่น นี้เกิดขึ้นโดยทั่วไปเรียกหรือObject.wait()
Thread.join()
จากนั้นเธรดจะยังคงอยู่ในสถานะนี้จนกว่าเธรดอื่นจะเรียกObject.notify()
หรือตาย
Object.wait()
โดยตรง แต่คุณจะอยู่ในWAITING
สถานะที่ใช้โครงสร้างการทำงานพร้อมกันระดับสูงเช่นการล็อกคิวการบล็อก ฯลฯ ... พูดอย่างกว้าง ๆ เมื่อใดก็ตามที่สองเธรดต้องประสานกัน
RUNNING
สถานะ
Thread.State
กล่าวว่า "... สถานะเหล่านี้เป็นสถานะเครื่องเสมือนซึ่งไม่สะท้อนสถานะเธรดของระบบปฏิบัติการใด ๆ " กล่าวอีกนัยหนึ่ง JVM ไม่สนใจเกี่ยวกับความแตกต่างระหว่างเธรดที่รันโค้ด Java เธรดที่รอการเรียกระบบเพื่อส่งคืนหรือเธรดที่รอการแบ่งเวลา ทั้งหมดRUNNABLE
นี้เป็นเรื่องที่ JVM เกี่ยวข้อง
WAITING
สถานะเธรดจะต้องไปที่BLOCKED
สถานะก่อนจนกว่าจะได้รับการล็อกที่เกี่ยวข้องกับอ็อบเจ็กต์ที่รออยู่
ความแตกต่างที่สำคัญระหว่างสถานะที่ถูกบล็อกและสถานะรอคือผลกระทบต่อตัวกำหนดตารางเวลา เธรดในสถานะที่ถูกบล็อกกำลังต่อสู้เพื่อการล็อก เธรดนั้นยังคงนับเป็นสิ่งที่ตัวกำหนดตารางเวลาต้องการให้บริการซึ่งอาจได้รับการรวมเข้ากับการตัดสินใจของตัวกำหนดตารางเวลาเกี่ยวกับระยะเวลาในการให้เธรดที่รันอยู่ (เพื่อให้เธรดสามารถปิดกั้นการล็อกได้)
เมื่อเธรดอยู่ในสถานะรอความเค้นบนระบบจะถูกย่อให้เล็กสุดและตัวกำหนดตารางเวลาก็ไม่ต้องกังวลกับมัน จะอยู่เฉยๆจนกว่าจะได้รับการแจ้งเตือน ยกเว้นความจริงที่ว่ามันทำให้เธรด OS ว่างอยู่มันจะไม่สามารถเล่นได้ทั้งหมด
นี่เป็นเหตุผลว่าทำไมการใช้ alertAll จึงน้อยกว่าในอุดมคติทำให้เกิดเธรดจำนวนมากที่ก่อนหน้านี้อยู่เฉยๆอย่างมีความสุขทำให้ระบบไม่ต้องตื่นขึ้นมาโดยที่ส่วนใหญ่จะบล็อกจนกว่าพวกเขาจะได้รับการล็อคค้นหาเงื่อนไขที่เป็นอยู่ การรอนั้นไม่เป็นความจริงและกลับไปรอ ขอแนะนำให้แจ้งเฉพาะชุดข้อความที่มีโอกาสคืบหน้าเท่านั้น
(การใช้ ReentrantLock แทนการล็อกภายในช่วยให้คุณมีหลายเงื่อนไขสำหรับการล็อกเดียวเพื่อให้คุณสามารถตรวจสอบให้แน่ใจว่าเธรดที่แจ้งเตือนนั้นเป็นเธรดที่รออยู่ในเงื่อนไขเฉพาะหลีกเลี่ยงข้อผิดพลาดการแจ้งเตือนการสูญหายในกรณีที่เธรดได้รับการแจ้งเตือน สิ่งที่ไม่สามารถดำเนินการได้)
มุมมองที่ง่ายขึ้นสำหรับการตีความการทิ้งเธรด:
RUNNABLE
ไม่ถูกต้องเสียทีเดียว อาจอยู่ในคิวการรัน Java แต่ไม่ดำเนินการหรืออาจเรียกใช้โค้ด Java ไม่จำเป็นต้องเรียกร้องให้เจ้าของที่ดิน
ถูกบล็อก - เธรดของคุณอยู่ในสถานะที่รันได้ของวงจรชีวิตเธรดและพยายามรับอ็อบเจ็กต์ล็อก รอ - เธรดของคุณอยู่ในสถานะรอของวงจรชีวิตเธรดและรอให้สัญญาณแจ้งเตือนเข้าสู่สถานะที่รันได้ของเธรด
ดูตัวอย่างนี้:
การสาธิตสถานะเธรด
/*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();
}
}
}
}