ทำความเข้าใจ java.lang.Thread.State: กำลังรอ (ที่จอดรถ)


91

อย่างแรกเป็นคำถามที่โง่มากฉันแค่สงสัยว่าคำว่า 'ที่จอดรถ' ที่รออยู่หมายความว่าอย่างไร กระทู้รอจอดอยู่หรือเพิ่งจอดจึงอยู่ในสถานะรอ? และเมื่อจอดรถนั้นจะใช้ทรัพยากร cpu / หน่วยความจำไปเท่าไหร่? จุดประสงค์ของการจอดด้ายคืออะไร?

ประการที่สองโดยดูที่วิธีการจอดในjava thread API

ปิดใช้งานเธรดปัจจุบันเพื่อจุดประสงค์ในการตั้งเวลาเธรดเว้นแต่จะมีใบอนุญาต

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

ภาษาอังกฤษไม่ใช่ภาษาหลักของฉันดังนั้นฉันจึงมีปัญหาในการทำความเข้าใจฉันตั้งใจให้ 'อนุญาต' เป็น 'อนุญาตให้จอดกระทู้' ดังนั้นคำถามที่ตามมา:

  • ความหมายของสิ่งนั้นคือ 'ใบอนุญาต' คืออะไรและใครจะตรวจสอบใบอนุญาตเหล่านั้นได้อย่างไร?
  • นั่นหมายความว่าอย่างไร: 'ถ้ามีใบอนุญาตก็จะถูกใช้ไป' มันถูก 'จอด' หรือไม่?
  • ต่อไปนี้ถ้าจุดที่สองเป็นจริงดังนั้นความแตกต่างระหว่าง 'ที่จอดรถ' และ 'อยู่เฉยๆ' คืออะไร? ถ้าฉันมีใบอนุญาตฉันสามารถจอดได้ตลอดไปและถ้าไม่ฉันสามารถทำให้มัน 'อยู่เฉยๆ' ได้?

ขอบคุณ

คำตอบ:


37

ใบอนุญาตหมายถึงการอนุญาตให้ดำเนินการต่อไป ที่จอดรถหมายถึงการระงับการดำเนินการจนกว่าจะได้รับอนุญาต

ซึ่งแตกต่างจากการSemaphoreอนุญาตการอนุญาตLockSupportจะเชื่อมโยงกับเธรด (กล่าวคืออนุญาตให้กับเธรดเฉพาะ) และไม่สะสม (กล่าวคือสามารถมีได้เพียงหนึ่งเธรดอนุญาตต่อเธรดเมื่อเธรดใช้การอนุญาตเธรดจะหายไป)

unpark()คุณสามารถให้ใบอนุญาตไปด้ายโดยการเรียก ด้ายสามารถระงับการดำเนินการจนกว่าใบอนุญาตใช้ได้ (หรือด้ายถูกขัดจังหวะหรือหมดเวลาหมดอายุ ฯลฯ ) park()โดยการเรียก เมื่อมีใบอนุญาตเธรดที่จอดอยู่จะใช้มันและออกจากpark()เมธอด


2
ดังนั้นสมมติว่าถ้าเธรด A เรียก 'จอด' สำหรับเธรด B แต่มีใบอนุญาตซึ่งเป็น 'B ไม่สามารถจอดได้' ดังนั้นการเรียกโดย A เพียงแค่กลับและ B จะไม่จอด มิฉะนั้นเมื่อไม่มีใบอนุญาต B จะต้องปฏิบัติตาม ดังนั้นการรอ (ที่จอดรถ) หมายความว่า "A พยายามจอดรถเพราะฉันไม่มีใบอนุญาต แต่ตอนนี้ทำไม่ได้ดังนั้นฉันจึงบล็อก A ด้วย" ขออภัยสำหรับประโยคนี้ยาว ฉันคิดว่าการรอนี้ค่อนข้างใช้ทรัพยากรมาก ฉันยังคงสงสัยว่าใครเป็นคนจัดการเรื่องใบอนุญาตทั้งหมด ใคร / อะไรกำลังตัดสินว่าบางเธรดมีใบอนุญาตในขณะที่บางเธรดไม่ได้รับอนุญาต
Leonardo

2
@ เลโอนาร์โด: กระทู้จอดได้ แต่ตัวเองไม่มีทางไปสวนกระทู้อื่นได้ ดังนั้นการโทรจึงpark()หมายความว่า "ฉันต้องการระงับการดำเนินการจนกว่าเธรดอื่นจะอนุญาตให้ฉันโทรหาunpark()"
axtavt

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

นอกจากนี้ WAITING (ที่จอดรถ) หมายความว่ากำลังรอที่จะจอดหรืออยู่ในสถานะรอหลังจากจอดแล้ว? ขออภัยฉันรู้ว่านี่เป็นคำถามที่โง่ :-)
Leonardo

3
@ Leonardo: หมายถึงสถานะรอหลังจากจอด
axtavt

11

ตามเอกสารสถานะเธรด java เธรดสามารถไปที่สถานะรอได้ด้วยเหตุผลสามประการ:

  1. Object.wait โดยไม่มีการหมดเวลา
  2. Thread.join โดยไม่มีการหมดเวลา
  3. LockSupport.park

เมื่อคุณเรียกใช้วิธีการจอดบนเธรดจะปิดใช้งานเธรดเพื่อวัตถุประสงค์ในการจัดกำหนดการเธรดเว้นแต่จะมีใบอนุญาต คุณสามารถเรียกใช้วิธีการยกเลิกการตรึงเพื่อให้มีใบอนุญาตสำหรับเธรดที่กำหนดหากยังไม่มี

ดังนั้นเมื่อเธรดของคุณอยู่ในโหมดรอโดย LockSupport.park มันจะแสดงว่าคุณกำลังรอ (ที่จอดรถ)

โปรดทราบว่าคุณสามารถโทรหาสวนสาธารณะในเธรดปัจจุบันเท่านั้น นี่เป็นกลไกที่มีประโยชน์มากในการใช้รูปแบบการออกแบบผู้ผลิตและผู้บริโภค


3

จากคำอธิบายคลาส (ที่ด้านบนของLockSupport javadoc ) ซึ่งอธิบายถึงการอนุญาต:

คลาสนี้เชื่อมโยงกับแต่ละเธรดที่ใช้มันคือใบอนุญาต (ในความหมายของคลาส Semaphore) การเรียกให้จอดจะกลับมาทันทีหากมีใบอนุญาตให้ใช้[ใบอนุญาต]ในกระบวนการ มิฉะนั้น[การเรียกให้จอด]อาจปิดกั้น การโทรเพื่อยกเลิกการจอดจะทำให้ใบอนุญาตใช้ได้หากยังไม่มี (ซึ่งแตกต่างจาก Semaphores แม้ว่าการอนุญาตจะไม่สะสมมีอย่างน้อยหนึ่งอย่าง)

(ฉันขยาย[ข้อความ]เพื่อให้อ่านง่ายขึ้นสำหรับผู้ที่ไม่ใช้ภาษาอังกฤษ)

หวังว่าใครสักคนที่มีความเข้าใจลึกซึ้งสามารถอธิบายเรื่องนี้ได้อย่างละเอียด ดูคำตอบของ axtavt

เป็นบันทึกสุดท้ายคำพูดสุดท้ายจาก javadoc:

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


3

ส่วนที่ทำให้ฉันกลับมาทบทวนคำถามนี้ซึ่งฉันไม่สามารถเข้าใจได้ในขณะที่อ่านเอกสารคือ:

ถ้ามีใบอนุญาตก็จะหมดและโทรกลับทันที ...

ดังนั้นเมื่อได้รับใบอนุญาตคือ "ใช้ได้" ที่และวิธีการที่ทำให้มันสามารถใช้ได้เพื่อที่จะสามารถได้รับการบริโภคได้ทันทีหรือไม่ นี่เป็นเรื่องเล็กน้อยที่จะค้นหา:

public static void main(String[] args) {

    Thread parkingThread = new Thread(() -> {
        System.out.println("Will go to sleep...");
        sleepTwoSeconds();
        System.out.println("Parking...");
        // this call will return immediately since we have called  LockSupport::unpark
        // before this method is getting called, making the permit available
        LockSupport.park();
        System.out.println("After parking...");
    });

    parkingThread.start();

    // hopefully this 1 second is enough for "parkingThread" to start
    // _before_ we call un-park
    sleepOneSecond();
    System.out.println("Un-parking...");
    // making the permit available while the thread is running and has not yet
    // taken this permit, thus "LockSupport.park" will return immediately
    LockSupport.unpark(parkingThread);

}

private static void sleepTwoSeconds() {
    try {
        Thread.sleep(1000 * 2);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private static void sleepOneSecond() {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}    

รหัสพูดสำหรับตัวมันเองไฟล์ threadกำลังทำงานแต่ยังไม่ถูกเรียกLockSupport.parkในขณะที่เธรดอื่น ๆ เรียกLockSupport.unparkใช้ - ทำให้มีใบอนุญาต หลังจากนั้นเราโทรไปLockSupport.parkและส่งคืนทันทีตั้งแต่มีใบอนุญาต

เมื่อคุณคิดแล้วนี่เป็นเรื่องที่อันตรายเล็กน้อยหากคุณเปิดเผยเธรดของคุณกับรหัสบางอย่างที่คุณไม่ได้ควบคุมและรหัสนั้นเรียกLockSupport.unparkในขณะที่คุณparkหลังจากนั้นมันอาจไม่ทำงาน


ประเด็นที่ดีมากฉันคิดว่ากิจกรรมการให้ใบอนุญาต - เช่นการเรียกไม่จอด () - จะเกี่ยวข้องเฉพาะเมื่อเธรดกำลังจอดอยู่
Alfred Xiao

@AlfredXiao เห็นด้วยนี่เป็นสิ่งที่ทำให้ฉันประหลาดใจเช่นกัน แต่มันก็สมเหตุสมผลฉันเดา
Eugene

1

ตามที่ฉันเข้าใจ "ใบอนุญาต" เป็นเพียงวัตถุที่แสดงว่าเธรดสามารถ "ไม่ได้ใส่เครื่องหมาย" ได้หรือไม่ และนี่คือการตรวจสอบโดย Thread เอง (หรือ de JRE เมื่อคุณพยายามจอดเธรด) สิ่งที่ "ถูกใช้" ฉันเข้าใจว่าใบอนุญาตหายไปและเธรดไม่ได้ถูกยกเลิก

ฉันคิดว่าคุณควรเรียนรู้เพิ่มเติมเล็กน้อยเกี่ยวกับมัลติเธรด .. คิดว่ามันเป็นเครื่องจ่ายที่มีวัตถุที่เรียกว่า "อนุญาต" คุณบอกให้เธรดจอดและเธรดตรวจสอบเครื่องจ่ายหากมี "ใบอนุญาต" เธรดจะนำไปและออก (โดยไม่มีที่จอด) หากไม่มี "ใบอนุญาต" ในเครื่องจ่ายเธรดจะถูกจอดไว้จนกว่าจะมี "ใบอนุญาต" (และคุณสามารถใส่ "ใบอนุญาต" ในเครื่องจ่ายด้วยunparkในตู้ด้วย

สำหรับการใช้งาน CPU / หน่วยความจำฉันคิดว่าขึ้นอยู่กับ OS ฯลฯ ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.