การสื่อสารเธรดใช้เพื่อให้แน่ใจว่าการทำงานร่วมกันของเธรด โดยทั่วไปจะต้องพิจารณาการสื่อสารเธรดเมื่อทำการซิงโครไนซ์เธรด
1. การสื่อสารเธรดแบบดั้งเดิม
โดยปกติจะใช้วิธีการสามวิธีโดยคลาส ObjectLT:
วิธีการทั้งสามนี้จะต้องเรียกโดยวัตถุตรวจสอบการซิงโครไนซ์และแบ่งออกเป็นสองสถานการณ์:
เมื่อวิธีการซิงโครไนซ์เนื่องจากการตรวจสอบการซิงโครไนซ์เป็นวัตถุนี้วิธีการทั้งสามนี้สามารถเรียกได้โดยตรง
ตัวอย่างมีดังนี้:
คลาสสาธารณะ syncMethodthreadCommunication {คลาสคงที่ dataWrap {int data = 0; ธงบูลีน = เท็จ; โมฆะที่ซิงโครไนซ์สาธารณะ addthreada () {ถ้า (ธง) {ลอง {wait (); } catch (interruptedException e) {e.printStackTrace (); }} data ++; System.out.println (thread.currentthread (). getName () + "" + ข้อมูล); ธง = จริง; แจ้ง(); } โมฆะที่ซิงโครไนซ์สาธารณะ addThreadb () {ถ้า (! ธง) {ลอง {รอ (); } catch (interruptedException e) {e.printStackTrace (); }} data ++; System.out.println (thread.currentthread (). getName () + "" + ข้อมูล); ธง = เท็จ; แจ้ง(); }} ชั้นเรียนแบบคงที่ threada ขยายเธรด {ข้อมูล dataWrap ส่วนตัว; public threada (dataWrap dataWrap) {this.data = dataWrap; } @Override โมฆะสาธารณะ Run () {สำหรับ (int i = 0; i <10; i ++) {data.addthreada (); }}} ThreadB คลาสคงที่ขยายเธรด {ข้อมูล DataWrap ส่วนตัว; Public ThreadB (DatawRap DataWrap) {this.data = dataWrap; } @Override โมฆะสาธารณะเรียกใช้ () {สำหรับ (int i = 0; i <10; i ++) {data.addThreadb (); }}} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {// ใช้สองเธรดเพื่อเพิ่มข้อมูลในการหมุน dataWrap dataWrap = new dataWrap (); threada ใหม่ (datawrap) .start (); ThreadB ใหม่ (DatawRap) .start (); -เมื่อซิงโครไนซ์บล็อกโค้ดคุณต้องใช้วัตถุมอนิเตอร์เพื่อเรียกใช้วิธีการทั้งสามนี้
ตัวอย่างมีดังนี้:
คลาสสาธารณะ SyncBlockThreadComminication {คลาสคงที่ DataWrap {ธงบูลีน; ข้อมูล int; } คลาสสแตติก threada ขยายเธรด {dataWrap dataWrap; public threada (dataWrap dataWrap) {this.dataWrap = dataWrap; } @Override โมฆะสาธารณะเรียกใช้ () {สำหรับ (int i = 0; i <10; i ++) {ซิงโครไนซ์ (dataWrap) {ถ้า (dataWrap.flag) {ลอง {dataWrap.wait (); } catch (interruptedException e) {e.printStackTrace (); }} dataWrap.data ++; System.out.println (getName () + "" + datawrap.data); dataWrap.flag = true; datawrap.notify (); }}}}} ThreadB คลาสคงที่ขยายเธรด {dataWrap dataWrap; Public ThreadB (DatawRap DataWrap) {this.datawRap = dataWrap; } @Override โมฆะสาธารณะเรียกใช้ () {สำหรับ (int i = 0; i <10; i ++) {ซิงโครไนซ์ (dataWrap) {ถ้า (! dataWrap.flag) {ลอง {dataWrap.wait (); } catch (interruptedException e) {e.printStackTrace (); }} dataWrap.data ++; System.out.println (getName () + "" + datawrap.data); dataWrap.flag = false; datawrap.notify (); }}}} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {// ใช้สองเธรดเพื่อเพิ่มข้อมูลในการหมุน dataWrap dataWrap = new dataWrap (); threada ใหม่ (datawrap) .start (); ThreadB ใหม่ (DatawRap) .start (); -2. ใช้เงื่อนไขเพื่อควบคุมการสื่อสารเธรด
เมื่อใช้วัตถุล็อคเพื่อให้แน่ใจว่ามีการซิงโครไนซ์วัตถุเงื่อนไขจะใช้เพื่อให้แน่ใจว่ามีการประสานงาน
ตัวอย่างมีดังนี้:
นำเข้า java.util.concurrent.locks.condition; นำเข้า java.util.concurrent.locks.lock; นำเข้า java.util.concurrent.locks.reentrantlock; นำเข้า com.sun.sound.riffinvaliddaException; {คลาสคงที่ DatawRap {int data; ธงบูลีน; ล็อคครั้งสุดท้ายส่วนตัว = ใหม่ reentrantlock (); เงื่อนไขขั้นสุดท้ายส่วนตัว = lock.newCondition (); โมฆะสาธารณะ addthreada () {lock.lock (); ลอง {ถ้า (ธง) {ลอง {edition.await (); } catch (interruptedException e) {e.printStackTrace (); }} data ++; System.out.println (thread.currentthread (). getName () + "" + ข้อมูล); ธง = จริง; เงื่อนไข. signal (); } ในที่สุด {lock.unlock (); }} โมฆะสาธารณะ addThreadB () {lock.lock (); ลอง {if (! Flag) {ลอง {edition.await (); } catch (interruptedException e) {e.printStackTrace (); }} data ++; System.out.println (thread.currentthread (). getName () + "" + ข้อมูล); ธง = เท็จ; เงื่อนไข. signal (); } ในที่สุด {lock.unlock (); }}} คลาสคงที่เธรดขยายเธรด {dataWrap dataWrap; public threada (dataWrap dataWrap) {this.dataWrap = dataWrap; } @Override โมฆะสาธารณะเรียกใช้ () {สำหรับ (int i = 0; i <10; i ++) {dataWrap.addthreada (); }}} ThreadB คลาสคงที่ขยายเธรด {dataWrap dataWrap; Public ThreadB (DatawRap DataWrap) {this.datawRap = dataWrap; } @Override โมฆะสาธารณะเรียกใช้ () {สำหรับ (int i = 0; i <10; i ++) {dataWrap.addThreadb (); }}} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {// ใช้สองเธรดเพื่อเพิ่มข้อมูลในการหมุน dataWrap dataWrap = new dataWrap (); threada ใหม่ (datawrap) .start (); ThreadB ใหม่ (DatawRap) .start (); -การรอคอย (), singal () และ singalall () ของวัตถุเงื่อนไขสอดคล้องกับวิธีการรอ (), แจ้ง () และ notifyall () วิธีการตามลำดับ
3. ใช้การบล็อกคิวการบล็อกคิวเพื่อควบคุมการสื่อสารเธรด
BlockingQueue เป็นอินเตอร์เฟสย่อยของอินเทอร์เฟซคิวซึ่งส่วนใหญ่ใช้สำหรับการสื่อสารเธรด มันมีคุณสมบัติ: เมื่อเธรดผู้ผลิตพยายามที่จะใส่องค์ประกอบลงใน BlockingQueue ถ้าคิวเต็มเธรดจะถูกบล็อก; เมื่อเธรดผู้บริโภคพยายามที่จะนำองค์ประกอบออกจาก blockingqueue ถ้าคิวว่างเปล่าเธรดจะถูกบล็อก คุณสมบัติทั้งสองนี้สอดคล้องกับสองวิธีที่รองรับการบล็อกใส่ (e e) และใช้ ()
ตัวอย่างมีดังนี้:
นำเข้า java.util.concurrent.arrayblockingqueue; นำเข้า java.util.concurrent.blockingqueue; การปิดกั้นระดับสาธารณะการปิดกั้น QublockQueuethreadComminication {dataWrap คลาสคงที่ {ข้อมูล int; } ชั้นเรียนแบบคงที่ threada ขยายเธรด {ส่วนตัว blockingqueue <DataWrap> blockingqueue; Public Threada (BlockingQueue <DatawRap> BlockingQueue, ชื่อสตริง) {super (ชื่อ); this.blockingqueue = blockingqueue; } @Override โมฆะสาธารณะเรียกใช้ () {สำหรับ (int i = 0; i <100; i ++) {ลอง {dataWrap dataWrap = blockingqueue.take (); datawrap.data ++; System.out.println (getName () + "" + datawrap.data); นอนหลับ (1,000); } catch (interruptedException e) {e.printStackTrace (); }}}}} ThreadB คลาสคงที่ขยายเธรด {ส่วนตัว blockingQueue <DataWRAP> blockingqueue; DataWrap Private DataWrap; Public ThreadB (BlockingQueue <DatawRap> BlockingQueue, DatawRap DataWrap, ชื่อสตริง) {super (ชื่อ); this.blockingqueue = blockingqueue; this.datawRap = dataWrap; } @Override โมฆะสาธารณะเรียกใช้ () {สำหรับ (int i = 0; i <100; i ++) {ลอง {dataWrap.data ++; System.out.println (getName () + "" + datawrap.data); blockingqueue.put (datawrap); นอนหลับ (1,000); } catch (interruptedException e) {e.printStackTrace (); }}}} โมฆะคงที่สาธารณะหลัก (สตริง [] args) {/// ใช้สองเธรดเพื่อเพิ่มข้อมูลในการหมุน dataWrap dataWrap = new dataWrap (); BlockingQueue <DatawRap> blockingQueue = new ArrayBlockingQueue <> (1); Threada ใหม่ (BlockingQueue, "ผู้บริโภค"). Start (); Threadb ใหม่ (BlockingQueue, DatawRap, "Producer"). Start (); -BlockingQueue มีห้าคลาสการใช้งาน:
arrayblockingqueue blockingqueue queue ตามการใช้งานอาร์เรย์
LinkedBlockingqueue blockingqueue queue ตามรายการที่เชื่อมโยง
องค์ประกอบใน PriorityBlockingQueue จำเป็นต้องใช้อินเทอร์เฟซที่เปรียบเทียบได้และการสั่งซื้อขององค์ประกอบจะถูกปรับแต่งตามตัวเปรียบเทียบ
Synchronousqueue ซิงโครไนซ์คิวโดยกำหนดให้การดำเนินการเข้าถึงบนคิวจะต้องดำเนินการสลับกัน
องค์ประกอบการรวบรวม DelayQueue จะต้องใช้อินเตอร์เฟสการหน่วงเวลาและองค์ประกอบในคิวจะถูกเรียงลำดับตามค่าการส่งคืนของวิธีการเชื่อมต่อการหน่วงเวลา getDelay ()
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น