เช่นเดียวกับผู้คนที่เกิด แก่ ป่วย และตาย เส้นด้ายยังต้องผ่านสถานะที่แตกต่างกันสี่สถานะ: เริ่มต้น (รอ) วิ่ง หยุด และหยุด สถานะทั้งสี่นี้สามารถควบคุมได้โดยใช้วิธีการในคลาสเธรด วิธีการที่เกี่ยวข้องกับสถานะทั้งสี่นี้ในคลาสเธรดมีดังต่อไปนี้
// หยุดและปลุกเธรด
public void resume( ); // ไม่แนะนำให้ใช้
โมฆะสาธารณะระงับ ( ); // ไม่แนะนำให้ใช้
การนอนหลับเป็นโมฆะสาธารณะ (มิลลิวินาทียาว);
การนอนหลับเป็นโมฆะสาธารณะแบบคงที่ (มิลลิวินาทียาว, int nanos);
//ยุติเธรด
public void stop( ); // ไม่แนะนำให้ใช้
โมฆะสาธารณะขัดจังหวะ ( );
// รับสถานะเธรด
บูลีนสาธารณะ isAlive ( );
บูลีนสาธารณะถูกขัดจังหวะ ( );
บูลีนคงที่สาธารณะถูกขัดจังหวะ ( );
// วิธีการเข้าร่วม
โมฆะสาธารณะเข้าร่วม () พ่น InterruptedException;
เธรดไม่ได้รันโค้ดในวิธีการ run ทันทีหลังจากถูกสร้างขึ้น แต่อยู่ในสถานะรอ เมื่อเธรดอยู่ในสถานะรอ คุณสามารถตั้งค่าคุณลักษณะต่างๆ ของเธรดผ่านวิธีการของคลาสเธรด เช่น ลำดับความสำคัญของเธรด (setPriority) ชื่อเธรด (setName) และประเภทเธรด (setDaemon)
เมื่อมีการเรียกเมธอด start เธรดจะเริ่มรันโค้ดในเมธอด run เธรดเข้าสู่สถานะกำลังทำงาน คุณสามารถใช้เมธอดisAliveของคลาสเธรดเพื่อตรวจสอบว่าเธรดกำลังทำงานอยู่หรือไม่ เมื่อเธรดอยู่ในสถานะกำลังทำงาน isAlive จะส่งกลับค่าจริง เมื่อ isAlive ส่งคืนค่าเท็จ เธรดอาจอยู่ในสถานะรอหรืออยู่ในสถานะหยุดทำงาน รหัสต่อไปนี้สาธิตการสลับระหว่างสามสถานะของการสร้างเธรด การรันและการหยุด และส่งออกค่าที่ส่งคืน isAlive ที่สอดคล้องกัน
LifeCycle คลาสสาธารณะขยายเธรด
-
การรันโมฆะสาธารณะ ()
-
อินท์ n = 0;
ในขณะที่ ((++n) < 1,000);
-
โมฆะคงที่สาธารณะ main (String [] args) พ่นข้อยกเว้น
-
วงจรชีวิต thread1 = วงจรชีวิตใหม่ ();
System.out.println("isAlive: " + thread1.isAlive());
thread1.start();
System.out.println("isAlive: " + thread1.isAlive());
thread1.join(); // รอให้เธรด thread1 สิ้นสุดก่อนที่จะดำเนินการต่อไป
System.out.println("thread1 สิ้นสุดแล้ว!");
System.out.println("isAlive: " + thread1.isAlive());
-
-
ผลลัพธ์ของการรันโค้ดด้านบน:
เมื่อเธรดเริ่มดำเนินการตามวิธีการเรียกใช้ เธรดนั้นจะไม่ออกจนกว่าวิธีการเรียกใช้จะเสร็จสมบูรณ์ อย่างไรก็ตาม ในระหว่างการดำเนินการของเธรด มีสองวิธีที่สามารถใช้เพื่อหยุดการดำเนินการของเธรดชั่วคราวได้ ทั้งสองวิธีนี้ถูกระงับและเข้าสู่โหมดสลีป หลังจากใช้การระงับเพื่อระงับเธรด คุณสามารถปลุกเธรดโดยใช้วิธีการดำเนินการต่อ หลังจากใช้โหมดสลีปเพื่อทำให้เธรดสลีป เธรดสามารถอยู่ในสถานะพร้อมหลังจากเวลาที่ตั้งไว้เท่านั้น (หลังจากเธรดสลีปสิ้นสุดลง เธรดอาจไม่ดำเนินการทันที แต่จะเข้าสู่สถานะพร้อมเท่านั้น โดยรอให้ระบบกำหนดเวลา) .
แม้ว่าการระงับและดำเนินการต่อสามารถระงับและปลุกเธรดได้อย่างง่ายดาย แต่การใช้ทั้งสองวิธีนี้อาจทำให้เกิดสิ่งที่คาดเดาไม่ได้เกิดขึ้น ดังนั้นทั้งสองวิธีนี้จึงถูกทำเครื่องหมายว่าเลิกใช้แล้ว (ประท้วง) ซึ่งบ่งชี้ว่าในทั้งสองวิธีนี้อาจถูกลบใน jdk ในอนาคต เวอร์ชันต่างๆ ดังนั้นอย่าพยายามใช้ทั้งสองวิธีนี้เพื่อใช้งานเธรด รหัสต่อไปนี้สาธิตการใช้วิธี sleep, Suspend และ Resume
MyThread คลาสสาธารณะขยายเธรด
-
คลาส SleepThread ขยายเธรด
-
การรันโมฆะสาธารณะ ()
-
พยายาม
-
นอนหลับ(2000);
-
จับ (ยกเว้น e)
-
-
-
-
การรันโมฆะสาธารณะ ()
-
ในขณะที่(จริง)
System.out.println(ใหม่ java.util.Date().getTime());
-
โมฆะคงที่สาธารณะ main (String [] args) พ่นข้อยกเว้น
-
เธรด MyThread = MyThread ใหม่ ();
SleepThread sleepThread = thread.new SleepThread();
sleepThread.start(); // เริ่มรันเธรด sleepThread
sleepThread.join(); // ดีเลย์เธรด sleepThread เป็นเวลา 2 วินาที
เธรด.เริ่มต้น();
ธงบูลีน = เท็จ;
ในขณะที่(จริง)
-
sleep(5000); // หน่วงเวลาเธรดหลักเป็นเวลา 5 วินาที
ธง = !ธง;
ถ้า (ธง)
เธรด.ระงับ();
อื่น
เธรด.เรซูเม่();
-
-
-
มีสองประเด็นที่ควรทราบเมื่อใช้วิธีการสลีป:
1. วิธีสลีปมีสองรูปแบบที่โอเวอร์โหลด หนึ่งในรูปแบบที่โอเวอร์โหลดไม่เพียงแต่สามารถตั้งค่ามิลลิวินาทีเท่านั้น แต่ยังรวมถึงนาโนวินาทีด้วย (1,000,000 นาโนวินาทีเท่ากับ 1 มิลลิวินาที) อย่างไรก็ตาม เครื่องเสมือน Java บนแพลตฟอร์มระบบปฏิบัติการส่วนใหญ่ไม่แม่นยำถึงระดับนาโนวินาที ดังนั้น หากตั้งค่าระดับนาโนวินาทีสำหรับโหมดสลีป เครื่องเสมือน Java จะใช้เวลามิลลิวินาทีที่ใกล้เคียงกับค่านี้มากที่สุด
2. เมื่อใช้วิธีการ sleep คุณต้องใช้การ Throw หรือ try{…}catch{…} จะส่ง InterruptedException เมื่อขัดจังหวะเธรดโดยใช้วิธีการขัดจังหวะ (วิธีการนี้จะกล่าวถึงใน 2.3.3) วิธีการนอนหลับถูกกำหนดดังนี้:
มีสามวิธีในการยุติเธรด
1. ใช้แฟล็ก exit เพื่อทำให้เธรดออกจากการทำงานตามปกติ นั่นคือ เธรดยุติลงเมื่อวิธีการรันเสร็จสมบูรณ์
2. ใช้วิธีหยุดเพื่อบังคับยุติเธรด (ไม่แนะนำวิธีนี้ เนื่องจากการหยุด เช่น การหยุดชั่วคราวและดำเนินการต่อ อาจให้ผลลัพธ์ที่คาดเดาไม่ได้เช่นกัน)
3. ใช้วิธีขัดจังหวะเพื่อขัดจังหวะเธรด
1. ยุติเธรดโดยใช้แฟล็กทางออก
เมื่อดำเนินการวิธีการรัน เธรดจะออก แต่บางครั้งวิธีการวิ่งก็ไม่มีวันสิ้นสุด ตัวอย่างเช่น มีการใช้เธรดในโปรแกรมเซิร์ฟเวอร์เพื่อตรวจสอบคำขอของไคลเอ็นต์ หรืองานอื่นๆ ที่ต้องมีการประมวลผลแบบวนรอบ ในกรณีนี้ งานเหล่านี้มักจะอยู่ในลูป เช่น ลูป while หากคุณต้องการให้ลูปทำงานตลอดไป คุณสามารถใช้ while(true){...} เพื่อจัดการมันได้ แต่ถ้าคุณต้องการออกจากลูป while ภายใต้เงื่อนไขบางประการ วิธีที่ตรงที่สุดก็คือการตั้งค่าแฟล็กประเภทบูลีน และตั้งค่าแฟล็กนี้เป็นจริงหรือเท็จเพื่อควบคุมว่าจะออกจากลูป while หรือไม่ ตัวอย่างของการยกเลิกเธรดโดยใช้แฟล็ก exit มีดังต่อไปนี้
ThreadFlag คลาสสาธารณะขยายเธรด
-
ทางออกบูลีนที่ผันผวนสาธารณะ = false;
การรันโมฆะสาธารณะ ()
-
ในขณะที่ (!ออก);
-
โมฆะคงที่สาธารณะ main (String [] args) พ่นข้อยกเว้น
-
ThreadFlag เธรด = ThreadFlag ใหม่ ();
เธรด.เริ่มต้น();
sleep(5000); // เธรดหลักล่าช้าเป็นเวลา 5 วินาที
thread.exit = true; // ยุติเธรดเธรด
เธรด.เข้าร่วม();
System.out.println("ออกจากเธรดแล้ว!");
-
-
2. ใช้วิธีหยุดเพื่อยุติเธรด
ใช้วิธีการหยุดเพื่อยุติเธรดที่ทำงานอยู่หรือถูกระงับอย่างแข็งขัน เราสามารถใช้รหัสต่อไปนี้เพื่อยุติเธรด:
3. ใช้วิธีขัดจังหวะเพื่อยุติเธรด
การใช้วิธีขัดจังหวะเพื่อยุติเธรดสามารถแบ่งออกเป็นสองสถานการณ์:
(1) เธรดอยู่ในสถานะที่ถูกบล็อก เช่น การใช้วิธีสลีป
(2) ใช้ while(!isInterrupted()){...} เพื่อตรวจสอบว่าเธรดถูกขัดจังหวะหรือไม่
ในกรณีแรกที่ใช้วิธีการขัดจังหวะ วิธีการนอนหลับจะส่งข้อยกเว้น InterruptedException ในขณะที่ในกรณีที่สอง เธรดจะออกโดยตรง รหัสด้านล่างแสดงให้เห็นถึงการใช้วิธีการขัดจังหวะในกรณีแรก
ThreadInterrupt คลาสสาธารณะขยายเธรด
-
การรันโมฆะสาธารณะ ()
-
พยายาม
-
นอนหลับ (50,000); // ล่าช้า 50 วินาที
-
จับ (InterruptedException e)
-
System.out.println(e.getMessage());
-
-
โมฆะคงที่สาธารณะ main (String [] args) พ่นข้อยกเว้น
-
เธรดเธรด = ThreadInterrupt ใหม่ ();
เธรด.เริ่มต้น();
System.out.println("กดปุ่มใดก็ได้ภายใน 50 วินาทีเพื่อขัดจังหวะเธรด!");
System.in.read();
เธรด.ขัดจังหวะ();
เธรด.เข้าร่วม();
System.out.println("กระทู้ออกแล้ว!");
-
-
การนอนหลับถูกขัดจังหวะ
กระทู้ออกแล้ว!
หมายเหตุ: มีสองวิธีในคลาส Thread เพื่อตรวจสอบว่าเธรดถูกยกเลิกโดยใช้วิธีการขัดจังหวะหรือไม่ วิธีแรกคือวิธีคงที่ซึ่งถูกขัดจังหวะ() และอีกวิธีหนึ่งคือวิธีที่ไม่คงที่คือInterrupted() ความแตกต่างระหว่างสองวิธีนี้คือการถูกขัดจังหวะเพื่อพิจารณาว่าเธรดปัจจุบันถูกขัดจังหวะหรือไม่ ในขณะที่ isInterrupted สามารถใช้เพื่อตรวจสอบว่า เธรดอื่นถูกขัดจังหวะ ดังนั้น ในขณะที่ (!isInterrupted()) ยังสามารถแทนที่ด้วย while (!Thread.interrupted()) ได้อีกด้วย