ในบางสถานการณ์ เราต้องรอให้การดำเนินการเธรดเสร็จสิ้นก่อนที่จะดำเนินการขั้นตอนต่อไป ตัวอย่างเช่น บางโปรแกรมจำเป็นต้องเตรียมใช้งานทรัพยากรบางอย่างก่อนที่จะเริ่มดำเนินการ ในเวลานี้ เราสามารถเริ่มเธรดโดยเฉพาะเพื่อทำงานการเริ่มต้น และรอจนกว่างานเธรดจะเสร็จสิ้นก่อนที่จะดำเนินการส่วนอื่นๆ
เพื่อจุดประสงค์นี้ คลาส Thread จัดเตรียมเมธอด join() ให้กับเรา เมื่อเราเรียกเมธอดนี้โดยใช้อ็อบเจ็กต์เธรด การเรียกอ็อบเจ็กต์เธรดจะล่าช้าจนกว่าวัตถุที่ถูกเรียกจะดำเนินการเสร็จสิ้นก่อนที่จะเริ่มดำเนินการ
ในส่วนนี้ โปรแกรมตัวอย่างจะสาธิตการรอให้วิธีการเริ่มต้นดำเนินการให้เสร็จสิ้นก่อนที่จะดำเนินการงานอื่นๆ
รู้ว่ามัน
ทำตามขั้นตอนที่แสดงด้านล่างเพื่อเสร็จสิ้นโปรแกรมตัวอย่าง
1. สร้างคลาสชื่อ DataSourcesLoader และใช้อินเทอร์เฟซ Runnable รหัสมีดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
DataSourcesLoader ระดับสาธารณะใช้งาน Runnable {
2. ใช้เมธอด run() พิมพ์ข้อความไปยังคอนโซลเพื่อระบุจุดเริ่มต้นของการดำเนินการ จากนั้นเข้าสู่โหมดสลีปเป็นเวลา 4 วินาที จากนั้นพิมพ์ข้อความไปยังคอนโซลเพื่อระบุการสิ้นสุดการประมวลผลเธรด รหัสมีดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
@แทนที่
โมฆะสาธารณะวิ่ง () {
System.out.printf("กำลังโหลดแหล่งข้อมูลเริ่มต้น: %s/n",
วันที่ใหม่ ());
พยายาม {
TimeUnit.SECONDS.sleep (4);
} จับ (InterruptedException e) {
e.printStackTrace();
-
System.out.printf("การโหลดแหล่งข้อมูลเสร็จสิ้น: %s/n",
วันที่ใหม่ ());
-
3. สร้างคลาสชื่อ NetworkConnectionsLoader และใช้อินเทอร์เฟซ Runnable ใช้เมธอด run() โค้ดของเมธอดนี้เหมือนกับเมธอด run() ของคลาส DataSourcesLoader ยกเว้นว่าจะพักเป็นเวลา 6 วินาที
4. นำคลาสหลักของตัวอย่างไปใช้และใช้เมธอด main() รหัสมีดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
ชั้นเรียนสาธารณะหลัก {
โมฆะคงที่สาธารณะ main (String [] args) {
5. สร้างวัตถุ DataSourcesLoader และวัตถุ Thread เพื่อเริ่มการดำเนินการ รหัสมีดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
DataSourcesLoader dsLoader = DataSourcesLoader ใหม่ ();
เธรด thread1 = เธรดใหม่ (dsLoader, "DataSourcesLoader");
6. สร้างวัตถุ NetworkConnectionsLoader และวัตถุ Thread เพื่อเริ่มการดำเนินการ รหัสมีดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
NetworkConnectionsLoader ncLoader = ใหม่ NetworkConnectionsLoader();
เธรด thread2 = เธรดใหม่ (ncLoader, "NetworkConnectionsLoader");
7. เรียกเมธอด start() ของวัตถุ Thread ทั้งสอง รหัสมีดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
thread1.start();
thread2.start();
8. เรียกใช้เมธอด join() เพื่อรอให้ทั้งสองเธรดทำงานให้เสร็จสิ้น วิธีนี้จะโยน InterruptedException ดังนั้นให้จับข้อยกเว้นนี้ รหัสมีดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
พยายาม {
thread1.join();
thread2.เข้าร่วม();
} จับ (InterruptedException e) {
e.printStackTrace();
-
9. พิมพ์ประโยคไปยังคอนโซลเพื่อระบุการสิ้นสุดการทำงานของโปรแกรม รหัสมีดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
System.out.printf("หลัก: โหลดการกำหนดค่าแล้ว: %s/n",
วันที่ใหม่ ());
10. รันโปรแกรมและตรวจสอบผลการดำเนินการ
รู้ว่าทำไม
เมื่อรันโปรแกรมตัวอย่างนี้ เราจะเห็นเธรดสองตัวเริ่มต้นการดำเนินการ ขั้นแรก DataSourcesLoader จะดำเนินการให้เสร็จสิ้น จากนั้น NetworkConnectionsLoader จะดำเนินการให้เสร็จสิ้น ณ จุดนี้ เธรดหลักยังคงดำเนินการต่อไป และจากนั้น พิมพ์ข้อความการสิ้นสุดไปยังคอนโซล
ไม่มีวันสิ้นสุด
Java มีวิธีการเข้าร่วม () ที่โอเวอร์โหลดอีกสองวิธี:
คัดลอกรหัสรหัสดังต่อไปนี้:
เข้าร่วม (มิลลิวินาทียาว)
เข้าร่วม (มิลลิวินาทียาว, นาโนยาว)
เมธอดแรกไม่รอจนกระทั่งการเรียกทำงานให้เสร็จสิ้น แต่จะรอตามเวลาที่ระบุโดยพารามิเตอร์ก่อนเริ่มดำเนินการ ตัวอย่างเช่น หาก thread1 เรียกใช้เมธอดนี้ thread1.join(1000) เมื่อเธรด thread1 ตรงกับหนึ่งในนั้น เงื่อนไขต่อไปนี้จะดำเนินการต่อไป:
1.thread2 ดำเนินการเสร็จสิ้น
2.หลังจาก 1,000 มิลลิวินาที;
เมื่อเงื่อนไขข้อใดข้อหนึ่งเป็นจริง เมธอด join() จะกลับมาและดำเนินการงานเดิมต่อไป
วิธีที่สองคล้ายกับวิธีแรกมาก ยกเว้นว่าจะมีพารามิเตอร์เวลานาโนวินาทีเพิ่มเติม
ใช้หลักคำสอน
บทความนี้แปลมาจาก "Java 7 Concurrency Cookbook" (D Gua Ge ขโมยมาในชื่อ "Java7 Concurrency Example Collection") และใช้เป็นสื่อการเรียนรู้เท่านั้น ห้ามนำไปใช้เพื่อวัตถุประสงค์ทางการค้าใดๆ โดยไม่ได้รับอนุญาต
ความสำเร็จเล็กๆ น้อยๆ
โค้ดตัวอย่างเวอร์ชันสมบูรณ์ที่ใช้ในส่วนนี้
รหัสที่สมบูรณ์ของคลาส DataSourcesLoader มีดังนี้:
แพ็คเกจ com.diguage.books.concurrencycookbook.chapter1.recipe6;
นำเข้า java.util.Date;
นำเข้า java.util.concurrent.TimeUnit;
-
* วันที่: 19-09-2556
* เวลา: 09:15 น
-
DataSourcesLoader ระดับสาธารณะใช้งาน Runnable {
@แทนที่
โมฆะสาธารณะวิ่ง () {
System.out.printf("กำลังโหลดแหล่งข้อมูลเริ่มต้น: %s/n",
วันที่ใหม่ ());
พยายาม {
TimeUnit.SECONDS.sleep (4);
} จับ (InterruptedException e) {
e.printStackTrace();
-
System.out.printf("การโหลดแหล่งข้อมูลเสร็จสิ้น: %s/n",
วันที่ใหม่ ());
-
-
รหัสที่สมบูรณ์ของคลาส NetworkConnectionsLoader
คัดลอกรหัสรหัสดังต่อไปนี้:
แพ็คเกจ com.diguage.books.concurrencycookbook.chapter1.recipe6;
นำเข้า java.util.Date;
นำเข้า java.util.concurrent.TimeUnit;
-
* วันที่: 19-09-2556
* เวลา: 09:21 น
-
NetworkConnectionsLoader ระดับสาธารณะใช้งาน Runnable {
@แทนที่
โมฆะสาธารณะวิ่ง () {
System.out.printf("กำลังโหลดแหล่งข้อมูลเริ่มต้น: %s/n",
วันที่ใหม่ ());
พยายาม {
TimeUnit.SECONDS.sleep (6);
} จับ (InterruptedException e) {
e.printStackTrace();
-
System.out.printf("การโหลดแหล่งข้อมูลเสร็จสิ้น: %s/n",
วันที่ใหม่ ());
-
-
รหัสที่สมบูรณ์ของคลาสหลัก
คัดลอกรหัสรหัสดังต่อไปนี้:
แพ็คเกจ com.diguage.books.concurrencycookbook.chapter1.recipe6;
นำเข้า java.util.Date;
-
* วันที่: 19-09-2556
* เวลา: 09:25 น
-
ชั้นเรียนสาธารณะหลัก {
โมฆะคงที่สาธารณะ main (String [] args) {
DataSourcesLoader dsLoader = DataSourcesLoader ใหม่ ();
เธรด thread1 = เธรดใหม่ (dsLoader, "DataSourcesLoader");
NetworkConnectionsLoader ncLoader = ใหม่ NetworkConnectionsLoader();
เธรด thread2 = เธรดใหม่ (ncLoader, "NetworkConnectionsLoader");
thread1.start();
thread2.start();
พยายาม {
thread1.join();
thread2.เข้าร่วม();
} จับ (InterruptedException e) {
e.printStackTrace();
-
System.out.printf("หลัก: โหลดการกำหนดค่าแล้ว: %s/n",
วันที่ใหม่ ());
-
-