[英]Multiple Consumer Producer In Java
我試圖為消費者創建2個線程,為生產者創建2個線程。 所有4個線程都在爭用一種資源。 其中兩個試圖從資源中消費,而兩個試圖生產。
下面是代碼
package com.threading;
import java.util.ArrayList;
import java.util.List;
public class TestConsumerProducer2 {
protected static int maxSize = 2;
static class Consumer implements Runnable {
List<Integer> goods;
public Consumer(List<Integer> goods) {
this.goods = goods;
}
public void consume() {
synchronized (goods) {
if (goods.size() <= 0) {
try {
goods.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " >>>> consuming >>>" + goods.remove(0));
goods.notifyAll();
}
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
consume();
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
static class Producer implements Runnable {
List<Integer> goods;
public Producer(List<Integer> goods) {
this.goods = goods;
}
public void produce(int i) {
synchronized (goods) {
if (goods.size() >= maxSize) {
try {
goods.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ">>> producing >> " + i);
goods.add(i);
goods.notifyAll();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
produce(i);
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
List<Integer> goods = new ArrayList<>();
Consumer consumer = new Consumer(goods);
Producer producer = new Producer(goods);
Thread consumerWorker1 = new Thread(consumer);
Thread consumerWorker2 = new Thread(consumer);
Thread prroducerWorker1 = new Thread(producer);
Thread prroducerWorker2 = new Thread(producer);
consumerWorker1.start();
consumerWorker2.start();
prroducerWorker1.start();
prroducerWorker2.start();
try {
consumerWorker1.join();
consumerWorker2.join();
prroducerWorker1.join();
prroducerWorker2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Job completed >>>>");
}
}
程序輸出
線程2 >>>生產>> 0
線程1 >>>>消耗>>> 0
線程3 >>>生產>> 0
線程“ Thread-0”中的異常java.lang.IndexOutOfBoundsException:Index:0,Size:0 at java.util.ArrayList.rangeCheck(ArrayList.java:657)at java.util.ArrayList.remove(ArrayList.java:496) )在com.threading.TestConsumerProducer2 $ Consumer.consume(TestConsumerProducer2.java:27)在com.threading.TestConsumerProducer2 $ Consumer.run(TestConsumerProducer2.java:35)在java.lang.Thread.run(Thread.java:748)線程2 >>>生產>> 1
線程1 >>>>消耗>>> 0
線程3 >>>生產>> 1
線程1 >>>>消耗>>> 1
線程2 >>>生產>> 2
線程1 >>>>消耗>>> 1
線程3 >>>生產>> 2
線程1 >>>>消耗>>> 2
線程2 >>>生產>> 3
線程1 >>>>消耗>>> 2
線程2 >>>生產>> 4
線程3 >>>生產>> 3
線程1 >>>>消耗>>> 3
線程2 >>>生產>> 5
線程1 >>>>消耗>>> 4
線程3 >>>生產>> 4
線程1 >>>>消耗>>> 3
線程2 >>>生產>> 6線程1 >>>>消耗>>> 5
線程2 >>>生產>> 7
線程3 >>>生產>> 5
問題陳述:為什么沒有一個線程執行10次? 代碼中的死鎖情況在哪里? 當商品對象被使用者線程鎖定並且size <= 0時,為什么應該進入等待狀態,為什么會有IndexOutOfBoundsException?
更改代碼中if
到while
出現可解決此問題。
在Oracle網站上的“ Guarded Blocks”教程中有相關建議:
注意:始終在循環中調用wait,以測試正在等待的條件。 不要以為中斷是針對您正在等待的特定條件,還是該條件仍然為真。
(通過中斷,它們表示從等待中返回,而不一定是源自調用Thread.interrupt的人的實際中斷。)
關鍵點:
線程僅在檢查時擁有鎖時才知道商品清單的內容。
調用wait會放棄該鎖,從而允許其他線程在此線程處於休眠狀態時取得進展。
一旦線程放棄了鎖,先前對商品清單狀態所做的任何檢查將不再有效。
線程從等待狀態返回后,它已經重新獲得了鎖,但是線程需要重新評估條件檢查,否則它將作用於陳舊的信息。 在線程上次檢查條件的時間與當前時間之間可能發生了很多事情。 之所以會得到IllegalArgumentException,是因為當前線程假設在等待當前線程時,有另一個線程刪除了該線程。
package com.threading;
import java.util.ArrayList;
import java.util.List;
public class TestConsumerProducer2 {
protected static int maxSize = 2;
static class Consumer implements Runnable {
List<Integer> goods;
public Consumer(List<Integer> goods) {
this.goods = goods;
}
public void consume() {
synchronized (goods) {
while (goods.size() <= 0) {
try {
goods.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " >>>> consuming >>>" + goods.remove(0));
goods.notifyAll();
}
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
consume();
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
static class Producer implements Runnable {
List<Integer> goods;
public Producer(List<Integer> goods) {
this.goods = goods;
}
public void produce(int i) {
synchronized (goods) {
while (goods.size() >= maxSize) {
try {
goods.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ">>> producing >> " + i);
goods.add(i);
goods.notifyAll();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
produce(i);
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
List<Integer> goods = new ArrayList<>();
Consumer consumer = new Consumer(goods);
Producer producer = new Producer(goods);
Thread consumerWorker1 = new Thread(consumer);
Thread consumerWorker2 = new Thread(consumer);
Thread prroducerWorker1 = new Thread(producer);
Thread prroducerWorker2 = new Thread(producer);
consumerWorker1.start();
consumerWorker2.start();
prroducerWorker1.start();
prroducerWorker2.start();
try {
consumerWorker1.join();
consumerWorker2.join();
prroducerWorker1.join();
prroducerWorker2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Job completed >>>>");
}
}
代碼現在成功完成,輸出如下:
C:\>java com.threading.TestConsumerProducer2
Thread-2>>> producing >> 0
Thread-1 >>>> consuming >>>0
Thread-3>>> producing >> 0
Thread-0 >>>> consuming >>>0
Thread-2>>> producing >> 1
Thread-3>>> producing >> 1
Thread-0 >>>> consuming >>>1
Thread-1 >>>> consuming >>>1
Thread-2>>> producing >> 2
Thread-3>>> producing >> 2
Thread-0 >>>> consuming >>>2
Thread-1 >>>> consuming >>>2
Thread-2>>> producing >> 3
Thread-0 >>>> consuming >>>3
Thread-3>>> producing >> 3
Thread-1 >>>> consuming >>>3
Thread-2>>> producing >> 4
Thread-0 >>>> consuming >>>4
Thread-3>>> producing >> 4
Thread-1 >>>> consuming >>>4
Thread-2>>> producing >> 5
Thread-0 >>>> consuming >>>5
Thread-3>>> producing >> 5
Thread-1 >>>> consuming >>>5
Thread-2>>> producing >> 6
Thread-0 >>>> consuming >>>6
Thread-3>>> producing >> 6
Thread-1 >>>> consuming >>>6
Thread-2>>> producing >> 7
Thread-0 >>>> consuming >>>7
Thread-3>>> producing >> 7
Thread-1 >>>> consuming >>>7
Thread-2>>> producing >> 8
Thread-0 >>>> consuming >>>8
Thread-3>>> producing >> 8
Thread-1 >>>> consuming >>>8
Thread-2>>> producing >> 9
Thread-0 >>>> consuming >>>9
Thread-3>>> producing >> 9
Thread-1 >>>> consuming >>>9
Job completed >>>>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.