1. แนวคิด
ปัญหาของผู้ผลิตและผู้บริโภคเป็นปัญหาของการทำงานร่วมกันแบบหลายเธรดใน Jindian ผู้ผลิตมีหน้าที่ผลิตผลิตภัณฑ์และเก็บไว้ในคลังสินค้า ผู้บริโภคได้รับผลิตภัณฑ์จากคลังสินค้าและบริโภค เมื่อคลังสินค้าเต็มผู้ผลิตจะต้องหยุดการผลิตจนกว่าจะมีที่ตั้งสำหรับผลิตภัณฑ์ที่จะเก็บไว้ เมื่อคลังสินค้าว่างเปล่าผู้บริโภคจะต้องหยุดการบริโภคจนกว่าจะมีผลิตภัณฑ์ในคลังสินค้า
เทคนิคต่อไปนี้ส่วนใหญ่ใช้เพื่อแก้ปัญหาผู้ผลิต/ผู้บริโภค: 1 ใช้เธรดเพื่อจำลองผู้ผลิตและจัดเก็บผลิตภัณฑ์อย่างต่อเนื่องในคลังสินค้าในวิธีการวิ่ง 2. ใช้เธรดเพื่อจำลองผู้บริโภคและรับผลิตภัณฑ์อย่างต่อเนื่องจากคลังสินค้าในวิธีการเรียกใช้ 3
. คลาสคลังสินค้าช่วยประหยัดผลิตภัณฑ์ เมื่อจำนวนผลิตภัณฑ์เป็น 0 วิธีการรอจะเรียกว่าทำให้เธรดผู้บริโภคปัจจุบันเข้าสู่สถานะรอ เมื่อมีการจัดเก็บผลิตภัณฑ์ใหม่วิธีการแจ้งเตือนจะถูกเรียกให้ตื่นขึ้นมาพร้อมกับเธรดผู้บริโภคที่รอคอย เมื่อคลังสินค้าเต็มวิธีการรอจะเรียกว่าทำให้เธรดผู้ผลิตปัจจุบันเข้าสู่สถานะรอ เมื่อผู้บริโภคได้รับผลิตภัณฑ์วิธีการแจ้งเตือนจะถูกเรียกให้ปลุกเธรดผู้ผลิตที่รอคอย
2. ตัวอย่าง
Package Book.Thread.Product; ผู้บริโภคระดับสาธารณะขยายเธรด {คลังสินค้าส่วนตัวคลังสินค้า; // คลังสินค้าที่ผู้บริโภคได้รับผลิตภัณฑ์บูลีนส่วนตัวที่ทำงาน = false; // เป็นบิตธงของเธรดสุดท้ายที่จำเป็นต้องมีผู้บริโภคสาธารณะ (คลังสินค้าคลังสินค้าชื่อสตริง) {super (ชื่อ); this.warehouse = คลังสินค้า; } public void start () {this.running = true; super.start (); } public void run () {ผลิตภัณฑ์ผลิตภัณฑ์; ลอง {ในขณะที่ (วิ่ง) {// รับผลิตภัณฑ์จากผลิตภัณฑ์คลังสินค้า = warehouse.getProduct (); นอนหลับ (500); }} catch (interruptedException e) {e.printStackTrace (); }} // หยุดกระทู้ของผู้บริโภคโมฆะสาธารณะ stopConsumer () {ซิงโครไนซ์ (คลังสินค้า) {this.running = false; warehouse.notifyall (); // แจ้งเธรดที่รอคอยคลังสินค้า}} // ว่าเธรดผู้บริโภคกำลังใช้บูลีนสาธารณะ isrunning () {return running; }} package book.thread.product; ผู้ผลิตชั้นสาธารณะขยายเธรด {คลังสินค้าส่วนตัว; // ผู้ผลิตจัดเก็บคลังสินค้าของผลิตภัณฑ์ส่วนตัวคงที่ int producename = 0; // ชื่อผลิตภัณฑ์บูลีนส่วนตัววิ่ง = เท็จ this.warehouse = คลังสินค้า; } public void start () {this.running = true; super.start (); } public void run () {ผลิตภัณฑ์ผลิตภัณฑ์; // ผลิตและจัดเก็บผลิตภัณฑ์ลอง {ในขณะที่ (ทำงาน) {product = ผลิตภัณฑ์ใหม่ ((++ productname)+""); this.warehouse.storageProduct (ผลิตภัณฑ์); นอนหลับ (300); }} catch (interruptedException e) {e.printStackTrace (); }} // หยุดกระทู้ของผู้ผลิตโมฆะสาธารณะ stopproducer () {ซิงโครไนซ์ (คลังสินค้า) {this.running = false; // แจ้งเธรดที่รอคลังสินค้าคลังสินค้าคลังสินค้าคลังสินค้า Notifyall (); }} // ว่าเธรดผู้ผลิตกำลังใช้บูลีนสาธารณะ isrunning () {return running; }} package book.thread.product; ผลิตภัณฑ์ระดับสาธารณะ {ชื่อสตริงส่วนตัว; // ชื่อผลิตภัณฑ์ผลิตภัณฑ์สาธารณะ (ชื่อสตริง) {this.name = name; } Public String ToString () {return "Product-"+Name; }} package book.thread.product; // คลาสคลังสินค้าของผลิตภัณฑ์ใช้อาร์เรย์เพื่อแสดงคิววงกลมเพื่อจัดเก็บผลิตภัณฑ์คลังสินค้าระดับสาธารณะของผลิตภัณฑ์ {ความจุ int คงที่ส่วนตัว = 11; // ความจุของผลิตภัณฑ์ส่วนตัวของคลังสินค้า Private Int ด้านหลัง = 0; // ตัวห้อยของผลิตภัณฑ์ที่ไม่ได้รับการรับรองล่าสุดในคลังสินค้าบวก 1 คลังสินค้าสาธารณะ () {this.products = ผลิตภัณฑ์ใหม่ [ความจุ]; } คลังสินค้าสาธารณะ (ความจุ int) {this (); if (ความจุ> 0) {ความจุ = ความจุ +1; this.products = ผลิตภัณฑ์ใหม่ [ความจุ]; }} // รับผลิตภัณฑ์จากคลังสินค้าผลิตภัณฑ์สาธารณะ getProduct () พ่น InterruptedException {ซิงโครไนซ์ (นี่) {boolean cumserrunning = true; // แท็กไม่ว่าเธรดผู้บริโภคจะยังคงใช้เธรด currentthread = thread.currentThread (); // รับเธรดปัจจุบัน } else {return null; // ไม่ใช่ผู้บริโภคสามารถรับผลิตภัณฑ์} // หากเธรดผู้บริโภคกำลังทำงานอยู่ แต่ไม่มีผลิตภัณฑ์ในคลังสินค้าเธรดผู้บริโภคยังคงรออยู่ในขณะที่ (ด้านหน้า == ด้านหลัง) && comperserrunning) {รอ (); comperserrunning = ((ผู้บริโภค) currentThread) .isrunning (); } // หากเธรดผู้บริโภคหยุดทำงานออกจากวิธีการและยกเลิกผลิตภัณฑ์ถ้า (! การหายาก) {return null; } // รับผลิตภัณฑ์แรกที่ไม่ได้ใช้ในผลิตภัณฑ์ผลิตภัณฑ์ปัจจุบัน = ผลิตภัณฑ์ [ด้านหน้า]; System.out.println ("ผู้บริโภค ["+currentthread.getName ()+"] getProduct:"+ผลิตภัณฑ์); // เลื่อนตัวห้อยของผลิตภัณฑ์ที่ไม่ได้รับการตรวจสอบในปัจจุบันกลับทีละหนึ่งถ้ามันถึงจุดสิ้นสุดของอาร์เรย์ให้ย้ายไปที่ส่วนหัวด้านหน้า = (ด้านหน้า+1+ความจุ)%ความจุ; System.out.println ("ปริมาณของผลิตภัณฑ์ที่ยังไม่ได้ใช้ในคลังสินค้า:"+(ด้านหลัง+ความจุด้านหน้า)%ความจุ); // แจ้งเธรดรออื่น ๆ แจ้งเตือน (); ผลิตภัณฑ์ส่งคืน; }} // การจัดเก็บผลิตภัณฑ์ไปยังคลังสินค้าโมฆะสาธารณะ storageProduct (ผลิตภัณฑ์ผลิตภัณฑ์) พ่น InterruptedException {ซิงโครไนซ์ (นี่) {บูลีน producerrunning = true; // ลงชื่อว่าเธรดผู้ผลิตกำลังใช้เธรด currentThread = thread.currentThread (); ถ้า (อินสแตนซ์ปัจจุบันของผู้ผลิต) {projecterrunning = ((ผู้ผลิต) currentThread) .isrunning (); } else {return; } // หากผลิตภัณฑ์ที่ไม่ได้รับการรับรองล่าสุดอยู่ถัดจากตัวห้อยของผลิตภัณฑ์ที่ไม่ได้รับการตรวจสอบครั้งแรกหมายความว่าไม่มีพื้นที่เก็บข้อมูล // หากไม่มีพื้นที่เก็บข้อมูลและเธรดผู้ผลิตยังคงทำงานอยู่เธรดผู้ผลิตจะรอให้คลังสินค้าปล่อยผลิตภัณฑ์ในขณะที่ (((หลัง+1) ความจุ%== ด้านหน้า) && producerrunning) {รอ (); Producterrunning = ((ผู้ผลิต) CurrentThread) .isrunning (); } // หากเธรดการผลิตหยุดทำงานพื้นที่เก็บข้อมูลของผลิตภัณฑ์จะหยุดลงหาก (! producerrunning) {return; } // บันทึกผลิตภัณฑ์ไปยังผลิตภัณฑ์คลังสินค้า [ด้านหลัง] = ผลิตภัณฑ์; System.out.println ("ผู้ผลิต [" + thread.currentthread (). getName () + "] storageProduct:" + ผลิตภัณฑ์); // เปลี่ยนตัวห้อยด้านหลังโดยอีกตัวหนึ่ง ด้านหลัง = (ด้านหลัง + 1)%ความจุ; System.out.println ("ปริมาณของผลิตภัณฑ์ที่ไม่ได้ใช้ในคลังสินค้า:" + (ด้านหลัง + ความจุ -หน้าความจุ)%); แจ้ง(); }}} Package Book.Thread.Product; Public Class TestProduct {โมฆะสาธารณะคงที่หลัก (String [] args) {คลังสินค้าคลังสินค้า = คลังสินค้าใหม่ (10); // สร้างคลังสินค้าที่มีความจุ 10 // สร้างกระทู้ผู้ผลิตและผู้ผลิตผู้ผลิต 1 = ผู้ผลิตรายใหม่ โปรดิวเซอร์ผู้ผลิต 2 = ผู้ผลิตรายใหม่ (คลังสินค้า "ผู้ผลิต -2"); โปรดิวเซอร์ผู้ผลิต 3 = ผู้ผลิตรายใหม่ (คลังสินค้า "ผู้ผลิต -3"); ผู้บริโภคผู้บริโภค 1 = ผู้บริโภคใหม่ (คลังสินค้า, "ผู้บริโภค -1"); ผู้บริโภคผู้บริโภค 2 = ผู้บริโภคใหม่ (คลังสินค้า, "ผู้บริโภค -2"); ผู้บริโภคผู้บริโภค 3 = ผู้บริโภคใหม่ (คลังสินค้า, "ผู้บริโภค -3"); ผู้บริโภคผู้บริโภค 4 = ผู้บริโภคใหม่ (คลังสินค้า "ผู้บริโภค -4"); // เริ่มเธรดผู้ผลิตและเธรดผู้บริโภคผลิต 1.start (); ผู้ผลิต 2.start (); Consumer1.start (); โปรดิวเซอร์ 3.start (); Consumer2.start (); Consumer3.Start (); Consumer4.start (); // ให้โปรแกรมผู้ผลิต/ผู้บริโภคทำงานสำหรับ 1600ms ลอง {thread.sleep (1600); } catch (interruptedException e) {e.printStackTrace (); } // หยุดเธรดผู้บริโภคผลิต 1.stopproducer (); Consumer1.StopConsumer (); ผู้ผลิต 2.stopproducer (); Consumer2.StopConsumer (); ผู้ผลิต 3.StopProducer (); Consumer3.StopConsumer (); Consumer4.StopConsumer (); -ผลลัพธ์ผลลัพธ์:
Producter [Producter-1] StorageProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้ใช้ในคลังสินค้า Product-1: 1Consumer [Consumer-2] GetProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้ถูกบริโภคในคลังสินค้า -1 คลังสินค้า: 0 Producer [PROUPTER-3] ของผลิตภัณฑ์ที่ไม่ได้ใช้ในคลังสินค้าผลิตภัณฑ์ 2: 2consumer [Consumer-3] GetProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้ถูกบริโภคในผลิตภัณฑ์ -3 Warehouse: 1Consumer [Consumer-1] GetProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้ใช้ในผลิตภัณฑ์ คลังสินค้า: 1Consumer [Consumer-4] GetProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้ถูกบริโภคในคลังสินค้าผลิตภัณฑ์ 4: 0 Producer [Producter-3] StorageProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้ใช้ในผลิตภัณฑ์ที่ไม่ได้ใช้จ่าย: 2Consumer [Consumer-1] GetProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้บริโภคในผลิตภัณฑ์ -6 Warehouse: 1Consumer [Consumer-2] GetProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้ถูกบริโภคในผลิตภัณฑ์ที่ 5: 0Producer [Productr-1] GetProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้ใช้ในคลังสินค้าผลิตภัณฑ์ 7: 0 Producer [Product-3] StorageProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้ใช้ในผลิตภัณฑ์ที่ 8: 1 Producer [Producer-2] ไม่ได้รับการบริโภคในคลังสินค้า: 1 Producer [product-1] StorageProduct: ผลิตภัณฑ์ 10 ผลิตภัณฑ์ที่ไม่ได้ถูกบริโภคในคลังสินค้า: 2 ProdAcer [Product-3] StorageProduct: ผลิตภัณฑ์จำนวน -11 ที่ไม่ได้บริโภค 4Consumer [Consumer-1] GetProduct: ผลิตภัณฑ์ -9 จำนวนผลิตภัณฑ์ที่ไม่ได้ถูกบริโภคในคลังสินค้า: 3CONSUMER [Consumer-2] GetProduct: ผลิตภัณฑ์ -10 จำนวนผลิตภัณฑ์ที่ไม่ได้ใช้ในคลังสินค้า: 2CONSUMER [Consumer-3] GetProduct StorageProduct: ผลิตภัณฑ์ -13 จำนวนผลิตภัณฑ์ที่ไม่ได้ใช้ในคลังสินค้า: 2Producer [product-1] StorageProduct: ผลิตภัณฑ์ 14 ผลิตภัณฑ์ที่ไม่ได้ถูกบริโภคในคลังสินค้า: 3 producer [ผู้ผลิต -2] บริโภคในคลังสินค้า: 3Consumer [Consumer-1] GetProduct: ผลิตภัณฑ์ -13 จำนวนผลิตภัณฑ์ที่ไม่ได้ถูกบริโภคในคลังสินค้า: 2CONSUMER [Consumer-2] GetProduct: ผลิตภัณฑ์ 14 ผลิตภัณฑ์ที่ไม่ได้บริโภคในคลังสินค้า 2 Producer [Producer-3] StorageProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้ใช้ในคลังสินค้าผลิตภัณฑ์ -17: 3 Producer [Product-2] StorageProduct: จำนวนผลิตภัณฑ์ที่ไม่ได้ใช้ในคลังสินค้าผลิตภัณฑ์ -18: 4
การวิเคราะห์: คลังสินค้าของผลิตภัณฑ์ถูกสร้างขึ้นในวิธีการหลักและคลังสินค้าไม่ได้เชื่อมโยง 3 เธรดผู้ผลิต 3 เธรดและ 4 เธรดผู้บริโภค เธรดเหล่านี้เริ่มทำให้โมเดลผู้ผลิต/ผู้บริโภคทำงานได้ เมื่อโปรแกรมทำงานเป็นเวลา 1600ms ผู้ผลิตทุกคนหยุดผลิตผลิตภัณฑ์และผู้บริโภคหยุดบริโภคผลิตภัณฑ์
ผลิตภัณฑ์เธรดผู้ผลิตผลิตผลิตภัณฑ์ที่ไม่มี 300ms ในวิธีการเรียกใช้และเก็บไว้ในคลังสินค้า ผู้บริโภคด้ายผู้บริโภคใช้ผลิตภัณฑ์จากคลังสินค้าโดยไม่มี 500ms ในวิธีการเรียกใช้
คลังสินค้ามีหน้าที่รับผิดชอบในการจัดเก็บและจัดจำหน่ายผลิตภัณฑ์ วิธีการเก็บข้อมูลของ StorageProduct มีหน้าที่จัดเก็บผลิตภัณฑ์ เมื่อคลังสินค้าเต็มเธรดปัจจุบันจะเข้าสู่สถานะรอนั่นคือถ้าผู้ผลิตเธรดการโทรวิธีการจัดเก็บ storageproduct เพื่อจัดเก็บผลิตภัณฑ์จะพบว่าคลังสินค้าเต็มและไม่สามารถเก็บไว้ได้มันจะเข้าสู่สถานะรอ เมื่อผลิตภัณฑ์จัดเก็บสำเร็จวิธีการแจ้งเตือนจะถูกเรียกให้ปลุกเธรดผู้บริโภคที่รอคอย
วิธีการ getProduct รับผิดชอบผลิตภัณฑ์ล่วงหน้า เมื่อคลังสินค้าว่างเปล่าเธรดปัจจุบันจะเข้าสู่สถานะรอ นั่นคือหากเธรดผู้บริโภค B เรียกวิธีการ GetProduct เพื่อรับผลิตภัณฑ์จะพบว่าคลังสินค้าว่างเปล่ามันจะเข้าสู่สถานะรอ เมื่อผลิตภัณฑ์ถูกสกัดสำเร็จวิธีการแจ้งเตือนจะถูกเรียกให้ปลุกเธรดผู้ผลิตที่รอคอย
บทความข้างต้นกล่าวถึงปัญหาของผู้ผลิตและผู้บริโภคในกระทู้ Java โดยสังเขปเป็นเนื้อหาทั้งหมดที่ฉันแบ่งปันกับคุณ ฉันหวังว่ามันจะให้ข้อมูลอ้างอิงและฉันหวังว่าคุณจะสนับสนุน wulin.com มากขึ้น