Java實現生產者消費者的方式有:wait && notify、BlockingQueue、Lock && Condition等
wait、notify注意事項:
(1)可以使用wait()和notify()方法在Java中實現線程間通信。不只是一個或兩個線程,而是多個線程可以使用這些方法相互通信。
(2)在synchronized方法或synchronized塊中調用wait(),notify()和notifyAll()方法,否則JVM將拋出IllegalMonitorStateException。
(3)從while(條件)循環調用wait和notify方法,而不是從if()塊調用,因為要重復檢查條件,而不僅僅是一次。
(4)多使用notifyAll方法而不是notify。
下面是wait、notify等待通知實現的生產者-消費者模式:
生產者:
/**
* 生產者
*
* @author monkjavaer
* @date 2018/12/15 11:13
*/
public class Producer implements Runnable {
/**
* 產品容器
*/
private final List<Integer> container;
public Producer(List<Integer> container) {
this.container = container;
}
/**
* 生產者生產方法
*
* @throws InterruptedException
*/
private void produce() throws InterruptedException {
//產品容器容量
int capacity = 5;
synchronized (container) {
//當容器已滿,暫停生產
while (container.size() == capacity) {
System.out.println("...容器已經滿了,暫停生產...");
container.wait();
}
Random random = new Random();
int p = random.nextInt(50);
//模擬1秒生產一個產品
TimeUnit.MILLISECONDS.sleep(1000);
System.out.println("生產產品:" + p);
container.add(p);
container.notifyAll();
}
}
@Override
public void run() {
while (true) {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("produce error");
}
}
}
}
消費者:
/**
* 消費者
* @author monkjavaer
* @date 2018/12/15 11:13
*/
public class Consumer implements Runnable{
/**
* 產品容器
*/
private final List<Integer> container;
public Consumer(List<Integer> container) {
this.container = container;
}
/**
* 消費者消費產品
*/
private void consume() throws InterruptedException {
synchronized (container){
while (container.isEmpty()){
System.out.println("...容器是空的,暫停消費...");
container.wait();
}
Integer p = container.remove(0);
//模擬1秒消費一個產品
TimeUnit.MILLISECONDS.sleep(1000);
System.out.println("消費產品:" + p);
container.notifyAll();
}
}
@Override
public void run() {
while (true){
try {
consume();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("consume error");
}
}
}
}
測試:
public class ProducerConsumerTest {
public static void main(String[] args) {
List<Integer> container = new ArrayList<>();
Thread producer = new Thread(new Producer(container));
Thread consumer = new Thread(new Consumer(container));
producer.start();
consumer.start();
}
}
輸出:
生產產品:14 生產產品:17 消費產品:14 生產產品:0 生產產品:39 生產產品:4 生產產品:3 ...容器已經滿了,暫停生產... 消費產品:17 消費產品:0 消費產品:39 消費產品:4 消費產品:3 ...容器是空的,暫停消費... 生產產品:25 生產產品:33 生產產品:17 消費產品:25 消費產品:33 消費產品:17 ...容器是空的,暫停消費...
