หลังจากดำเนินการ wait () เธรดจะรอนานเท่าใดหากไม่ได้รับการแจ้งเตือนจากเธรดอื่น

Aug 16 2020

ในตัวอย่างด้านล่างเนื่องจากเธรดหลักไม่ได้รับการแจ้งเตือนจากเธรดย่อยจึงควรรอตลอดไป แต่เธรดหลักกำลังดำเนินการและผลลัพธ์ของตัวอย่างด้านล่างคือ:

c
l
total: 19900

เหตุใดเธรดหลักจึงถูกเรียกใช้งาน

public class ThreadX extends Thread {
    static int total = 0;

    public void run() {
        synchronized (this) {
            for (int i = 0; i < 200; i++) {
                total = total + i;
            }
            System.out.println("c");

        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadX t = new ThreadX();

        t.start();
        synchronized (t) {
            t.wait();
            System.out.println("l");
        }

        System.out.println("total: " + total);

    }
}

คำตอบ

10 akuzminykh Aug 16 2020 at 09:58

ตอบคำถาม - ร่างกาย

ตรวจสอบThread#join(long):

[... ] เมื่อเธรดสิ้นสุดthis.notifyAllเมธอดจะถูกเรียกใช้ [... ]

สังเกตว่าThread#join()เรียกใช้ฟังก์ชันนั้นด้วย0ซึ่งหมายถึงตลอดไป

[... ] การหมดเวลาของ 0 หมายถึงการรอตลอดไป

ดังนั้นในกรณีของคุณที่นี่tเพียงแค่เรียกร้องเมื่อมันสิ้นสุดลงซึ่งแจ้งหลักหัวข้อที่กำลังรอnotifyAllt


พฤติกรรมที่ไม่เข้าใจง่ายนี้เป็นสาเหตุที่พวกเขาเขียนสิ่งต่อไปนี้ในเอกสารประกอบ:

ก็จะแนะนำว่าการใช้งานที่ไม่ได้ใช้wait, notifyหรือnotifyAllในThreadกรณี

ตอบคำถาม - ชื่อเรื่อง

ตรวจสอบObject#wait(หรือJLS (17.2.1. รอ) ):

เธรดสามารถปลุกได้โดยไม่ได้รับการแจ้งเตือนถูกขัดจังหวะหรือหมดเวลาซึ่งเรียกว่าการปลุกแบบปลอม ๆ แม้ว่าสิ่งนี้จะไม่ค่อยเกิดขึ้นในทางปฏิบัติ แต่แอปพลิเคชันจะต้องป้องกันโดยการทดสอบเงื่อนไขที่น่าจะทำให้เธรดถูกปลุกและรอต่อไปหากเงื่อนไขไม่เป็นที่พอใจ

ดังนั้นเธรดใน Java จึงสามารถปลุกได้ตลอดเวลา การปลุกแบบปลอม ๆ ไม่น่าจะเกิดขึ้นมากนักแต่ก็สามารถเกิดขึ้นได้