คัดลอกรหัสรหัสดังต่อไปนี้:
//เริ่มกระทู้
โมฆะสาธารณะเริ่มต้น ( );
การรันโมฆะสาธารณะ ( );
// หยุดและปลุกเธรด
public void resume( ); // ไม่แนะนำให้ใช้
โมฆะสาธารณะระงับ ( ); // ไม่แนะนำให้ใช้
การนอนหลับเป็นโมฆะสาธารณะ (มิลลิวินาทียาว);
การนอนหลับเป็นโมฆะสาธารณะแบบคงที่ (มิลลิวินาทียาว, int nanos);
//ยุติเธรด
public void stop( ); // ไม่แนะนำให้ใช้
โมฆะสาธารณะขัดจังหวะ ( );
// รับสถานะเธรด
บูลีนสาธารณะ isAlive ( );
บูลีนสาธารณะถูกขัดจังหวะ ( );
บูลีนคงที่สาธารณะถูกขัดจังหวะ ( );
// วิธีการเข้าร่วม
โมฆะสาธารณะเข้าร่วม () พ่น InterruptedException;
1. สร้างและเรียกใช้เธรด
เธรดไม่ได้รันโค้ดในวิธีการ run ทันทีหลังจากถูกสร้างขึ้น แต่อยู่ในสถานะรอ เมื่อเธรดอยู่ในสถานะรอ คุณสามารถตั้งค่าคุณลักษณะต่างๆ ของเธรดผ่านวิธีการของคลาสเธรด เช่น ลำดับความสำคัญของเธรด (setPriority) ชื่อเธรด (setName) และประเภทเธรด (setDaemon)
เมื่อมีการเรียกเมธอด start เธรดจะเริ่มรันโค้ดในเมธอด run เธรดเข้าสู่สถานะกำลังทำงาน คุณสามารถใช้เมธอดisAliveของคลาสเธรดเพื่อตรวจสอบว่าเธรดกำลังทำงานอยู่หรือไม่ เมื่อเธรดอยู่ในสถานะกำลังทำงาน isAlive จะส่งกลับค่าจริง เมื่อ isAlive ส่งคืนค่าเท็จ เธรดอาจอยู่ในสถานะรอหรืออยู่ในสถานะหยุดทำงาน รหัสต่อไปนี้สาธิตการสลับระหว่างสามสถานะของการสร้างเธรด การรันและการหยุด และส่งออกค่าที่ส่งคืน isAlive ที่สอดคล้องกัน
คัดลอกรหัสรหัสดังต่อไปนี้:
แพ็คเกจบทที่ 2;
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());
-
-
โปรดทราบว่าวิธีการรวมจะใช้ในโค้ดด้านบน ฟังก์ชันหลักของวิธีนี้คือเพื่อให้แน่ใจว่าโปรแกรมยังคงทำงานต่อไปหลังจากวิธีการรันของเธรดเสร็จสิ้น วิธีนี้จะแนะนำในบทความต่อๆ ไป
ผลลัพธ์ของการรันโค้ดด้านบน:
isAlive: เท็จ
isAlive: จริง
กระทู้ที่ 1 จบแล้ว!
isAlive: เท็จ
2. ระงับและปลุกเธรด
เมื่อเธรดเริ่มดำเนินการตามวิธีการเรียกใช้ เธรดนั้นจะไม่ออกจนกว่าวิธีการเรียกใช้จะเสร็จสมบูรณ์ อย่างไรก็ตาม ในระหว่างการดำเนินการของเธรด คุณสามารถหยุดการดำเนินการของเธรดชั่วคราวได้โดยใช้สองวิธี ทั้งสองวิธีนี้ถูกระงับและนอนหลับ หลังจากใช้การระงับเพื่อระงับเธรด คุณสามารถปลุกเธรดนั้นได้ด้วยวิธีการดำเนินการต่อ หลังจากใช้โหมดสลีปเพื่อทำให้เธรดสลีป เธรดสามารถอยู่ในสถานะพร้อมหลังจากเวลาที่ตั้งไว้เท่านั้น (หลังจากเธรดสลีปสิ้นสุดลง เธรดอาจไม่ดำเนินการทันที แต่จะเข้าสู่สถานะพร้อมเท่านั้น โดยรอให้ระบบกำหนดเวลา) .
แม้ว่าการระงับและดำเนินการต่อสามารถระงับและปลุกเธรดได้อย่างง่ายดาย แต่การใช้ทั้งสองวิธีนี้อาจทำให้เกิดสิ่งที่คาดเดาไม่ได้เกิดขึ้น ดังนั้นทั้งสองวิธีนี้จึงถูกทำเครื่องหมายว่าเลิกใช้แล้ว (ประท้วง) ซึ่งบ่งชี้ว่าในทั้งสองวิธีนี้อาจถูกลบใน jdk ในอนาคต เวอร์ชันต่างๆ ดังนั้นอย่าพยายามใช้ทั้งสองวิธีนี้เพื่อใช้งานเธรด รหัสต่อไปนี้สาธิตการใช้วิธี sleep, Suspend และ Resume
คัดลอกรหัสรหัสดังต่อไปนี้:
แพ็คเกจบทที่ 2;
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 วินาที
ธง = !ธง;
ถ้า (ธง)
เธรด.ระงับ();
อื่น
เธรด.เรซูเม่();
-
-
-
หากดูผิวเผินแล้ว ผลกระทบของการใช้โหมดสลีปและการระงับจะคล้ายกัน แต่วิธีสลีปไม่เทียบเท่ากับการระงับ ความแตกต่างที่ใหญ่ที่สุดระหว่างกันคือคุณสามารถระงับเธรดอื่นในเธรดเดียวโดยใช้วิธีการระงับ ตัวอย่างเช่น ในโค้ดข้างต้น เธรดเธรดจะถูกระงับในเธรดหลัก โหมดสลีปใช้งานได้เฉพาะกับเธรดที่กำลังดำเนินการอยู่เท่านั้น ในโค้ดข้างต้น sleepThread และเธรดหลักจะเข้าสู่โหมดสลีปเป็นเวลา 2 วินาทีและ 5 วินาทีตามลำดับ เมื่อใช้โหมดสลีป โปรดทราบว่าคุณไม่สามารถสลีปเธรดหนึ่งในอีกเธรดหนึ่งได้ ตัวอย่างเช่น การใช้เมธอด thread.sleep(2000) ในเมธอด main ไม่สามารถทำให้เธรดเธรดสลีปเป็นเวลา 2 วินาที แต่สามารถทำให้เธรดหลักสลีปได้เพียง 2 วินาทีเท่านั้น
มีสองประเด็นที่ควรทราบเมื่อใช้วิธีการสลีป:
1. วิธีสลีปมีสองรูปแบบที่โอเวอร์โหลด หนึ่งในรูปแบบที่โอเวอร์โหลดไม่เพียงแต่สามารถตั้งค่ามิลลิวินาทีเท่านั้น แต่ยังรวมถึงนาโนวินาทีด้วย (1,000,000 นาโนวินาทีเท่ากับ 1 มิลลิวินาที) อย่างไรก็ตาม เครื่องเสมือน Java บนแพลตฟอร์มระบบปฏิบัติการส่วนใหญ่ไม่แม่นยำถึงระดับนาโนวินาที ดังนั้น หากตั้งค่าระดับนาโนวินาทีสำหรับโหมดสลีป เครื่องเสมือน Java จะใช้เวลามิลลิวินาทีที่ใกล้เคียงกับค่านี้มากที่สุด
2. ต้องใช้ Throws หรือ try{...}catch{...} เมื่อใช้วิธีการ sleep เนื่องจากเมธอด run ไม่สามารถใช้การพ่นได้ คุณจึงสามารถใช้ได้เพียง try{...}catch{...} เท่านั้น เมื่อเธรดอยู่ในโหมดสลีปและใช้วิธีการขัดจังหวะ (วิธีการนี้จะกล่าวถึงใน 2.3.3) ใช้เพื่อขัดจังหวะเธรด โหมดสลีปจะส่ง InterruptedException วิธีการนอนหลับถูกกำหนดดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
โมฆะสาธารณะสลีป (มิลลิวินาทียาว) พ่น InterruptedException
การนอนหลับเป็นโมฆะแบบคงที่สาธารณะ (มิลลิวินาทียาว, int nanos) พ่น InterruptedException
3. สามวิธีในการยุติเธรด
มีสามวิธีในการยุติเธรด
1. ใช้แฟล็ก exit เพื่อทำให้เธรดออกจากการทำงานตามปกติ นั่นคือ เธรดยุติลงเมื่อวิธีการรันเสร็จสมบูรณ์
2. ใช้วิธีหยุดเพื่อบังคับยุติเธรด (ไม่แนะนำวิธีนี้ เนื่องจากการหยุด เช่น การหยุดชั่วคราวและดำเนินการต่อ อาจให้ผลลัพธ์ที่คาดเดาไม่ได้เช่นกัน)
3. ใช้วิธีขัดจังหวะเพื่อขัดจังหวะเธรด
1. ยุติเธรดโดยใช้แฟล็กทางออก
เมื่อดำเนินการวิธีการรัน เธรดจะออก แต่บางครั้งวิธีการวิ่งก็ไม่มีวันสิ้นสุด ตัวอย่างเช่น มีการใช้เธรดในโปรแกรมเซิร์ฟเวอร์เพื่อตรวจสอบคำขอของไคลเอ็นต์ หรืองานอื่นๆ ที่ต้องมีการประมวลผลแบบวนรอบ ในกรณีนี้ งานเหล่านี้มักจะอยู่ในลูป เช่น ลูป while หากคุณต้องการให้ลูปทำงานตลอดไป คุณสามารถใช้ while(true){...} เพื่อจัดการมันได้ แต่ถ้าคุณต้องการออกจาก while loop ภายใต้เงื่อนไขบางประการ วิธีที่ตรงที่สุดก็คือการตั้งค่าแฟล็กประเภทบูลีน และตั้งค่าแฟล็กนี้เป็นจริงหรือเท็จเพื่อควบคุมว่าจะออกจากลูป while หรือไม่ ตัวอย่างของการยกเลิกเธรดโดยใช้แฟล็ก exit มีดังต่อไปนี้
คัดลอกรหัสรหัสดังต่อไปนี้:
แพ็คเกจบทที่ 2;
ThreadFlag คลาสสาธารณะขยายเธรด
-
ทางออกบูลีนที่ผันผวนสาธารณะ = false;
การรันโมฆะสาธารณะ ()
-
ในขณะที่ (!ออก);
-
โมฆะคงที่สาธารณะ main (String [] args) พ่นข้อยกเว้น
-
ThreadFlag เธรด = ThreadFlag ใหม่ ();
เธรด.เริ่มต้น();
sleep(5000); // เธรดหลักล่าช้าเป็นเวลา 5 วินาที
thread.exit = true; // ยุติเธรดเธรด
เธรด.เข้าร่วม();
System.out.println("ออกจากเธรดแล้ว!");
-
-
ธงทางออก ทางออก ถูกกำหนดไว้ในโค้ดด้านบน เมื่อทางออกเป็นจริง ลูปในขณะที่ออก และค่าเริ่มต้นของทางออกจะเป็นเท็จ เมื่อกำหนด exit คีย์เวิร์ด Java volatile จะถูกใช้ จุดประสงค์ของคีย์เวิร์ดนี้คือเพื่อซิงโครไนซ์ exit ซึ่งหมายความว่ามีเพียงเธรดเดียวเท่านั้นที่สามารถแก้ไขค่าของ exit ในเวลาเดียวกัน
2. ใช้วิธีหยุดเพื่อยุติเธรด
ใช้วิธีการหยุดเพื่อยุติเธรดที่ทำงานอยู่หรือถูกระงับอย่างแข็งขัน เราสามารถใช้โค้ดต่อไปนี้เพื่อยุติเธรด:
เธรด.หยุด();
แม้ว่าการใช้โค้ดข้างต้นสามารถยุติเธรดได้ แต่การใช้วิธีหยุดนั้นเป็นอันตรายมาก เช่นเดียวกับการปิดเครื่องคอมพิวเตอร์กะทันหันแทนที่จะปิดเครื่องตามขั้นตอนปกติ อาจทำให้เกิดผลลัพธ์ที่คาดเดาไม่ได้ ดังนั้นจึงไม่แนะนำให้ใช้ วิธีการหยุดการยุติเธรด
3. ใช้วิธีขัดจังหวะเพื่อยุติเธรด
การใช้วิธีขัดจังหวะเพื่อยุติเธรดสามารถแบ่งออกเป็นสองสถานการณ์:
(1) เธรดอยู่ในสถานะที่ถูกบล็อก เช่น การใช้วิธีสลีป
(2) ใช้ while(!isInterrupted()){...} เพื่อตรวจสอบว่าเธรดถูกขัดจังหวะหรือไม่
ในกรณีแรกที่ใช้วิธีการขัดจังหวะ วิธีการนอนหลับจะส่งข้อยกเว้น InterruptedException ในขณะที่ในกรณีที่สอง เธรดจะออกโดยตรง รหัสด้านล่างแสดงให้เห็นถึงการใช้วิธีการขัดจังหวะในกรณีแรก
คัดลอกรหัสรหัสดังต่อไปนี้:
แพ็คเกจบทที่ 2;
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("กระทู้ออกแล้ว!");
-
-
ผลลัพธ์ของการรันโค้ดข้างต้นมีดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
กดปุ่มใดก็ได้ภายใน 50 วินาทีเพื่อขัดจังหวะเธรด!
การนอนหลับถูกขัดจังหวะ
กระทู้ออกแล้ว!
หลังจากเรียกเมธอดขัดจังหวะแล้ว เมธอด sleep จะส่งข้อยกเว้นแล้วแสดงข้อความแสดงข้อผิดพลาด: sleep Interrupted
หมายเหตุ: มีสองวิธีในคลาส Thread เพื่อตรวจสอบว่าเธรดถูกยกเลิกโดยใช้วิธีการขัดจังหวะหรือไม่ วิธีแรกคือวิธีคงที่ซึ่งถูกขัดจังหวะ() และอีกวิธีหนึ่งคือวิธีที่ไม่คงที่คือInterrupted() ความแตกต่างระหว่างสองวิธีนี้คือการถูกขัดจังหวะเพื่อพิจารณาว่าเธรดปัจจุบันถูกขัดจังหวะหรือไม่ ในขณะที่ isInterrupted สามารถใช้เพื่อตรวจสอบว่า เธรดอื่นถูกขัดจังหวะ ดังนั้น ในขณะที่ (!isInterrupted()) ยังสามารถแทนที่ด้วย while (!Thread.interrupted()) ได้อีกด้วย