Java Concurrency - นโยบายการหยุดชะงัก
ฉันอ่านJava Concurrency ในการปฏิบัติ ในส่วนนโยบายการหยุดชะงักในบทที่
การยกเลิกและการปิดระบบ
กล่าวถึง
งานไม่ควรถือว่าอะไรเกี่ยวกับนโยบายการหยุดชะงักของเธรดการดำเนินการเว้นแต่จะได้รับการออกแบบอย่างชัดเจนให้ทำงานภายในบริการที่มีนโยบายการหยุดชะงัก ไม่ว่างานจะตีความการขัดจังหวะเป็นการยกเลิกหรือดำเนินการอื่น ๆ กับการหยุดชะงักก็ควรดูแลรักษาสถานะการหยุดชะงักของเธรดการดำเนินการ ถ้ามันไม่แพร่กระจาย InterruptedException ไปยังผู้เรียกมันควรเรียกคืนสถานะการหยุดชะงักหลังจากจับ InterruptionException: Thread.currentThread (). interrupt ()
ดังนั้นฉันจึงพยายามเล่นกับตัวอย่างรายชื่อเพื่อทำความเข้าใจ แต่ฉันสับสนกับผลลัพธ์
PrimeProducer
public class CorrectPrimeProducer extends Thread {
private final BlockingQueue<BigInteger> queue;
public CorrectPrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+" interrupt status in producer:" + Thread.currentThread().isInterrupted());
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted()) {
queue.put(p = p.nextProbablePrime());
}
} catch (InterruptedException e) {
/* Allow thread to exit */
Thread.currentThread().interrupt();
System.out.println(Thread.currentThread().getName()+" interrupt status in producer catch:" + Thread.currentThread().isInterrupted());
}
}
}
วิธีการหลัก ##
public static void main(String[] args) throws InterruptedException {
BlockingQueue<BigInteger> primes = new LinkedBlockingQueue<>();
CorrectPrimeProducer generator = new CorrectPrimeProducer(primes);
generator.start();
try {
while (needMorePrimes()) {
consume(primes.take());
}
} finally {
generator.interrupt();
}
TimeUnit.SECONDS.sleep(5);
System.out.println(generator.getName()+" interrupt status in main:"+generator.isInterrupted());
}
//do something
private static void consume(BigInteger take) {
System.out.println(take);
}
private static int counter = 1;
private static boolean needMorePrimes() {
counter++;
if(counter == 10){
// after counter reaches 10 return false
return false;
}
return true;
}
เอาท์พุต:
// when TimeUnit.SECONDS.sleep(5); in main class is not commented
Thread-0 interrupt status in producer:false
2
3
5
7
11
13
17
19
Thread-0 interrupt status in producer catch:true
Thread-0 interrupt status in main:false
//When TimeUnit.SECONDS.sleep(5); in main class is commented
Thread-0 interrupt status in producer:false
2
3
5
7
11
13
17
19
Thread-0 interrupt status in main:true
Thread-0 interrupt status in producer catch:true
คำถาม
เพียงแค่เพิ่ม TimeUnit.SECONDS.sleep (5) ในเธรดหลักในคลาสหลัก สถานะการขัดจังหวะเธรด (เช่นตัวสร้าง) กำลังได้รับการรีเซ็ต ถ้าฉันแสดงความคิดเห็นเมธอด TimeUnit.SECONDS.sleep (5) ในกรณีนั้นสถานะการขัดจังหวะจะยังคงอยู่ เหตุใดจึงเกิดขึ้นและเกิดขึ้นได้อย่างไร?
ในหนังสือมีการกล่าวถึงเธรดควรถูกขัดจังหวะโดยเจ้าของเท่านั้น ในตัวอย่างข้างต้นใครเป็นเจ้าของ? ฉันคิดว่าเธรดวิธีหลักของมัน
คำตอบ
การเพิ่มTimeUnit.SECONDS.sleep(5)คุณกำลังให้เวลาเพียงพอสำหรับเธรดที่จะยุติ
เมื่อเธรดสิ้นสุดลงแฟล็กการขัดจังหวะจะถูกล้าง
สิ่งนี้ไม่ได้ระบุไว้ในข้อกำหนด แต่เป็นสิ่งที่เกิดขึ้น ดูตัวอย่างรายงานข้อบกพร่องนี้ :
ไม่มีการละเมิดข้อกำหนดใด ๆ ที่นี่ดังนั้นฉันจึงได้ส่งคำขอนี้เป็นการเพิ่มประสิทธิภาพแทนที่จะเป็นข้อบกพร่อง การขาดข้อกำหนดเป็นข้อบกพร่อง - เราตั้งใจระบุว่า "การขัดจังหวะหลังจากการยุติไม่จำเป็นต้องมีผลกระทบ" เพื่อจัดการกับข้อเท็จจริงที่ว่าสถานะการขัดจังหวะถูกเก็บไว้ใน VM และจะไม่มีอยู่อีกต่อไปเมื่อเธรดสิ้นสุดลง อย่างไรก็ตามเราละเลยที่จะสะท้อนให้เห็นว่าในข้อมูลจำเพาะ Thread.isInterrupted
หากไม่มีสิ่งพิเศษsleepฉันสงสัยว่าในทางทฤษฎีคุณสามารถเห็นทั้งสองสถานะtrueและfalseขัดจังหวะได้เนื่องจากมีสภาพการแข่งขัน แต่มีโอกาสมากที่คุณจะเห็นtrueเนื่องจากการตั้งเวลาเธรด หน้าต่างเวลาที่สถานะการขัดจังหวะเป็นเท็จระหว่างข้อยกเว้นที่ถูกโยนและสถานะการขัดจังหวะที่ถูกเรียกคืนในบล็อกการจับนั้นมีขนาดเล็กมากอย่างไม่น่าเชื่อ
เพียงแค่เพิ่ม TimeUnit.SECONDS.sleep (5) ในเธรดหลักในคลาสหลัก สถานะการขัดจังหวะเธรด (เช่นตัวสร้าง) กำลังได้รับการรีเซ็ต ถ้าฉันแสดงความคิดเห็นเมธอด TimeUnit.SECONDS.sleep (5) ในกรณีนั้นสถานะการขัดจังหวะจะยังคงอยู่ เหตุใดจึงเกิดขึ้นและเกิดขึ้นได้อย่างไร?
คุณไม่ได้ใช้กลไกการซิงโครไนซ์ใด ๆ (นอกเหนือจากการบล็อกคิว) ระหว่างเธรดหลักและCorrectPrimeProducerเมื่อเธรดหลักพิมพ์สถานะ - CorrectPrimeProducerอาจยังไม่ได้รักษาสถานะที่ถูกขัดจังหวะไว้ (โดยดำเนินการตามcatchคำแนะนำการบล็อก) ดังนั้นคุณจึงได้falseผลลัพธ์
เมื่อคุณเพิ่มลงsleepในเมนThreadคุณเพียงแค่เพิ่มความเป็นไปได้ที่CorrectPrimeProducerเธรดจะรักษาสถานะการหยุดชะงักโดยการเรียกใช้catchคำสั่งบล็อกก่อนที่เธรดหลักจะพยายามพิมพ์สถานะ trueนั่นคือเหตุผลที่มันพิมพ์
ในหนังสือมีการกล่าวถึงเธรดควรถูกขัดจังหวะโดยเจ้าของเท่านั้น ในตัวอย่างข้างต้นใครเป็นเจ้าของ? ฉันคิดว่าเธรดวิธีหลักของมัน
ในกรณีนี้คุณเป็นเจ้าของ (เจ้าของคือรหัสที่สร้างเธรด) ของCorrectPrimeProducerเธรดดังนั้นคุณจึงตัดสินใจว่าการหยุดชะงักหมายถึงอะไร ตัวอย่างเช่นคุณสามารถสร้างขึ้นใหม่ได้หากถูกขัดจังหวะ (สิ่งนี้เกิดขึ้นเช่นThreads จาก java thread pool โดยค่าเริ่มต้น)