1. المفهوم
مشكلة المنتجين والمستهلكين هي مشكلة في التعاون متعدد الخيوط في Jindian. المنتجون مسؤولون عن إنتاج المنتجات وتخزينها في المستودع ؛ يحصل المستهلكون على منتجات من المستودع ويستهلكونها. عندما يكون المستودع ممتلئًا ، يجب على المنتج إيقاف الإنتاج حتى يكون هناك موقع لتخزين المنتج ؛ عندما يكون المستودع فارغًا ، يجب أن يتوقف المستهلك عن الاستهلاك حتى يكون هناك منتج في المستودع.
تُستخدم التقنيات التالية بشكل أساسي لحل مشكلات المنتج/المستهلك: 1. استخدم مؤشرات الترابط لمحاكاة المنتجين وتخزين المنتجات باستمرار في المستودع في طريقة التشغيل. 2. استخدم المواضيع لمحاكاة المستهلكين والحصول على منتجات مستمرة من المستودع في طريقة التشغيل. 3
ال . فئة المستودع يحفظ المنتج. عندما يكون عدد المنتجات 0 ، يتم استدعاء طريقة الانتظار ، مما يؤدي إلى إدخال مؤشر ترابط المستهلك الحالي إلى حالة انتظار. عندما يتم تخزين منتج جديد ، يتم استدعاء طريقة الإخطار لإيقاظ موضوع المستهلك في الانتظار. عندما يكون المستودع ممتلئًا ، يتم استدعاء طريقة الانتظار ، مما يتسبب في إدخال مؤشر ترابط المنتج الحالي في حالة انتظار. عندما يحصل المستهلك على المنتج ، يتم استدعاء طريقة الإخطار لإيقاظ مؤشر ترابط منتج الانتظار.
2. أمثلة
Package Book.Thread.Product ؛ مستهلك الطبقة العامة يمتد Thread {Private Warehouse Warehouse ؛ // المستودع حيث يحصل المستهلك على تشغيل المنتج المنطقي الخاص = false ؛ this.warehouse = مستودع ؛ } public void start () {this.running = true ؛ Super.start () ؛ } public void run () {Product Product ؛ حاول {بينما (تشغيل) {// الحصول على منتج من منتج المستودع = warehouse.getProduct () ؛ النوم (500) ؛ }} catch (interruptedException e) {E.PrintStackTrace () ؛ }} // إيقاف مؤشر ترابط المستهلك public void stopconsumer () {synchronized (Warehouse) {this.running = false ؛ Warehouse.NotifyAll () ؛ // إخطار مؤشر الترابط في انتظار المستودع}} // ما إذا كان مؤشر ترابط المستهلك يعمل على تشغيل Boolean Isrunning () {return running ؛ }} package book.thread.product ؛ منتج الفئة العامة يمتد Thread {private Warehouse Warehouse ؛ // تخزن الشركة المصنعة مستودع المنتج الخاص بالمنتج الثابت الخاص بالمنتج = 0 ؛ this.warehouse = مستودع ؛ } public void start () {this.running = true ؛ Super.start () ؛ } public void run () {Product Product ؛ // إنتاج وتخزين المنتج جرب {بينما (تشغيل) {Product = New Product ((++ productName)+"") ؛ this.warehouse.storageProduct (المنتج) ؛ النوم (300) ؛ }} catch (interruptedException e) {E.PrintStackTrace () ؛ }} // إيقاف مؤشر ترابط المنتج public stopproducer () {Synchronized (Warehouse) {this.running = false ؛ // إخطار الموضوع في انتظار مستودع مستودع المستودعات. }} // ما إذا كان مؤشر ترابط المنتج يقوم بتشغيل boolean isrunning () {return running ؛ }} package book.Thread.Product ؛ Public Class Product {Private String Name ؛ // Name Promit Profere (اسم السلسلة) {this.name = name ؛ } السلسلة العامة toString () {return "Product-"+name ؛ }} package book.Thread.Product ؛ // تستخدم فئة المستودعات الخاصة بالمنتج صفيفًا لتمثيل قائمة انتظار دائرية لتخزين مستودع الفئة العامة للمنتج {Private Static int cuttor = 11 ؛ // لا تستهلك قدرة المستودع الخاص بالمنتجات الخاصة ؛ int REAN = 0 ؛ // CORPRICTIVE من آخر منتج غير مستهلك في المستودع بالإضافة إلى 1 مستودع عام () {this.products = منتج جديد [السعة] ؛ } المستودع العام (السعة int) {this () ؛ if (cumpt> 0) {cappary = caption +1 ؛ this.products = منتج جديد [السعة] ؛ }} // احصل على منتج من المنتجات العامة getProduct () Warehouse GetProduct () interruptedException {Synchronized (this) {boolean extracterRunning = true ؛ // tag tag armo that keasher keasure keathrunning = (current) {current) } آخر {return null ؛ // لا يمكن للمستهلك الحصول على المنتج} // إذا كان مؤشر ترابط المستهلك قيد التشغيل ، ولكن لا يوجد منتج في المستودع ، يستمر مؤشر ترابط المستهلك في الانتظار أثناء ((الأمام == الخلفي) && consumerrunning) {wait () ؛ ConsultRrunning = ((المستهلك) CurrentThread) .isrunning () ؛ } // إذا توقف مؤشر ترابط المستهلك عن التشغيل ، والخروج من الطريقة وإلغاء المنتج إذا (! consumerRunning) {return null ؛ } // احصل على المنتج الأول الذي لم يتم استهلاكه في منتج المنتج الحالي = المنتجات [Front] ؛ System.out.println ("المستهلك ["+currentThread.getName ()+"] getProduct:"+منتج) ؛ // حرك مجموعة المنتجات غير المستهلكة حاليًا واحدًا تلو الآخر ، إذا وصلت إلى نهاية الصفيف ، فانتقل إلى السعة في المقدمة (Front+1+) ٪ ؛ System.out.println ("كمية المنتجات التي لم يتم استهلاكها بعد في المستودع:"+(خلفية+سعة سعة) ٪ ٪) ؛ // إخطار موضوعات الانتظار الأخرى الإخطار () ؛ إرجاع المنتج ؛ }} // تخزين منتج إلى Warehouse Public Void StorageProduct (منتج المنتج) يلقي InterruptedException {Synchronized (this) {boolean producerrunning = true ؛ if (currentthread مثيل المنتج) {producerRunning = ((المنتج) currentThRead) .isrunning () ؛ } آخر {return ؛ } // إذا كان آخر منتج غير مستقر بجوار أول منتج غير مستهلك ، فهذا يعني أنه لا توجد مساحة تخزين. // إذا لم يكن هناك مساحة تخزين ولا يزال مؤشر ترابط المنتج قيد التشغيل ، فإن مؤشر ترابط المنتج ينتظر المستودع لإطلاق المنتج بينما (((خلفي+1) سعة == أمامي) && producerrunning) {wait () ؛ producerRunning = ((منتج) CurrentThread) .isrunning () ؛ } // إذا توقف مؤشر ترابط الإنتاج عن التشغيل ، فسيتم إيقاف تخزين المنتج إذا (! producerRunning) {return ؛ } // حفظ المنتج إلى منتجات المستودعات [الخلفية] = المنتج ؛ System.out.println ("Properger [" + thread.currentThRead (). getName () + "] StorageProduct:" + Product) ؛ // قم بتغيير المُخطط الخلفي بواحد تلو الآخر. الخلفية = (الخلفية + 1) ٪ ؛ System.out.println ("كمية المنتجات غير المستهلكة في المستودع:" + (خلفية + سعة -Ront) سعة ٪) ؛ إخطار () ؛ }}} package book.thread.product ؛ public class testProduct {public static void main (string [] args) {Warehouse Warehouse = New Warehouse (10) ؛ // إنشاء مستودع بسعة 10 // إنشاء مؤشرات ترابط المنتج ومنتجو المستهلكين 1 = منتج جديد (Warehouse ، "Proder-1") ؛ المنتجون المنتجون 2 = منتج جديد (Warehouse ، "Producer-2") ؛ المنتجون المنتجون 3 = منتج جديد (Warehouse ، "Producer-3") ؛ المستهلك المستهلك 1 = مستهلك جديد (المستودع ، "المستهلك -1") ؛ المستهلك المستهلك 2 = مستهلك جديد (مستودع ، "Consumer-2") ؛ المستهلك المستهلك 3 = مستهلك جديد (مستودع ، "مستهلك 3") ؛ المستهلك المستهلك 4 = مستهلك جديد (مستودع ، "مستهلك 4") ؛ // ابدأ مؤشر ترابط المنتج وموضوع المستهلك المنتج 1.start () ؛ Producers2.start () ؛ consumer1.start () ؛ المنتجون 33.start () ؛ consumer2.start () ؛ Consumer3.start () ؛ Consumer4.start () ؛ // اسمح لبرنامج المنتج/المستهلك بتشغيل 1600ms حاول {thread.sleep (1600) ؛ } catch (interruptedException e) {E.PrintStackTrace () ؛ } // إيقاف مؤشر ترابط المستهلك 1.stopProducer () ؛ consumer1.StopConsumer () ؛ Producers2.StopProducer () ؛ consumer2.stopConsumer () ؛ Producers3.StopProducer () ؛ consumer3.stopConsumer () ؛ consumer4.stopConsumer () ؛ }}نتيجة الإخراج:
المنتج [Produster-1] StorageProduct: عدد المنتجات التي لم يتم استهلاكها في مستودع المنتج -1: 1Consumer [Consumer-2] GetProduct: عدد المنتجات التي لم يتم استهلاكها في مستودع المنتج-1: من المنتجات التي لم يتم استهلاكها في مستودع المنتج -2: 2Consumer [المستهلك-3] GetProduct: عدد المنتجات التي لم يتم استهلاكها في مستودع المنتج 3: 1Consumer [Consumer-1] GetProduct: عدد المنتجات التي لم يتم استهلاكها في المنتج المستودع: 1Consumer [Consumer-4] GetProduct: عدد المنتجات التي لم يتم استهلاكها في مستودع Product-4: 0 Producer [Produster-3] StorageProduct: عدد المنتجات التي لم يتم استهلاكها في المنتجات-6 من المنتجات: 2Consumer [Consumer-1] GetProduct: عدد المنتجات التي لم يتم استهلاكها في مستودع المنتج-6: 1Consumer [Consumer-2] GetProduct: عدد المنتجات التي لم يتم استهلاكها في Product-5. GetProduct: عدد المنتجات التي لم يتم استهلاكها في مستودع Product-7: 0 Producer [Productr-3] منتج تخزين: عدد المنتجات التي لم يتم استهلاكها في المنتج-8 المنتجات التي تم استهلاكها: 2Consumer [producer-4] storageProduc لم يتم استهلاكها في المستودع: 1Producer [Productr-1] منتج التخزين: المنتج 10 عدد المنتجات التي لم يتم استهلاكها في المستودع: 2Producer [Productr-3] StorageProd-storeprod: عدد المنتجات التي لم يتم استهلاكها من المنتجات التي لم يتم استهلاكها في المنتج 4Consumer [Consumer-1] GetProduct: Product-9 عدد المنتجات التي لم يتم استهلاكها في المستودع: 3Consumer [Consumer-2] GetProduct: Product-10 عدد من المنتجات التي لم يتم استهلاكها في المستودع: 1Producer [producer] منتج التخزين: المنتج-13 من المنتجات التي لم يتم استهلاكها في المستودع: 2Producer [Productr-1] المنتج: المنتج -14 عدد المنتجات التي لم يتم استهلاكها في Warehouse: 3Consum [Producer-4]. استهلاك في المستودع: 3Consumer [Consumer-1] GetProduct: Product-13 عدد المنتجات التي لم يتم استهلاكها في المستودع: 2Consumer [Consumer-2] GetProduct: Product-14 عدد المنتجات التي لم يتم استهلاكها في المستودعات: 2Producer [Producer-3] StorageProduct: عدد المنتجات التي لم يتم استهلاكها في مستودع المنتج-17: 3Producer [Productr-2] StorageProdure: عدد المنتجات التي لم يتم استهلاكها في مستودع المنتج-18: 4
التحليل: تم إنشاء مستودع للمنتج في الطريقة الرئيسية ، ولا يربط المستودع 3 مؤشرات ترابط المنتجين و 4 مؤشرات ترابط المستهلك. بدأت هذه الخيوط في جعل نموذج المنتج/المستهلك يعمل. عندما يعمل البرنامج لمدة 1600 مللي ثانية ، يتوقف جميع المنتجين عن إنتاج المنتجات ويتوقف المستهلكون عن استهلاك المنتجات.
ينتج منتج مؤشر ترابط المنتج منتجًا بدون 300 مللي ثانية في طريقة التشغيل ويخزنه في المستودع ؛ يأخذ مستهلك مؤشر ترابط المستهلك منتجًا من المستودع بدون 500 مللي ثانية في طريقة التشغيل.
Warehouse مسؤول عن تخزين وتوزيع المنتجات. طريقة التخزين هي المسؤولة عن تخزين المنتج. عندما يكون المستودع ممتلئًا ، يدخل مؤشر الترابط الحالي إلى حالة انتظار ، أي إذا كان مؤشر ترابط المنتج A يستدعي طريقة StorageProduct لتخزين المنتج ، فإنه يجد أن المستودع ممتلئ ولا يمكن تخزينه ، فسوف يدخل حالة انتظار. عندما يكون منتج التخزين ناجحًا ، يتم استدعاء طريقة الإخطار لإيقاظ مؤشر ترابط المستهلك في الانتظار.
طريقة الحصول على المنتج هي المسؤولة عن المنتج مقدمًا. عندما يكون المستودع فارغًا ، يدخل الخيط الحالي إلى حالة انتظار. هذا هو ، إذا قام مؤشر ترابط المستهلك B باستدعاء طريقة GetProduct للحصول على المنتج ، فإنه يجد أن المستودع فارغ ، فسوف يدخل حالة انتظار. عندما يتم استخراج المنتج بنجاح ، يتم استدعاء طريقة الإخطار لإيقاظ مؤشر ترابط منتج الانتظار.
تناقش المقالة أعلاه باختصار مشاكل المنتجين والمستهلكين في خيوط Java هي كل المحتوى الذي أشاركه معك. آمل أن يعطيك مرجعًا وآمل أن تتمكن من دعم wulin.com أكثر.