Java實現生產者消費者的方式有:wait && notify、BlockingQueue、Lock && Condition等
wait、notify注意事項:
(1)可以使用wait()和notify()方法在Java中實現線程間通信。不只是一個或兩個線程,而是多個線程可以使用這些方法相互通信。
(2)在synchronized方法或synchronized塊中調用wait(),notify()和notifyAll()方法
(3)從while(條件)循環調用wait和notify方法,而不是從if()塊調用,因爲要重複檢查條件,而不僅僅是一次。
(4)使用notifyAll方法而不是notify,喚醒所有消費端。
相關代碼
MiddlewareChannel類-存儲生產者消息的通道
package com.java.test;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
/**
* 存儲 生產者消息的通道
* @author jiajie
*
*/
public class MiddlewareChannel {
public int init_capacity=0;//初始存儲
public int max_capacity=20;//最大存儲 最大容量值
/**
* 消息端產生消息
*
* @param message
*/
public synchronized void send() {
//判斷通道是否已滿
if(init_capacity > max_capacity) { //已滿
try {
System.out.println("庫存已滿,生產者等待發送信息...");
//生產者 等待發送消息
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
//通知消費者 消費消息
System.out.println(Thread.currentThread().getName()+":生產消息" +"庫存容量:"+(++init_capacity));
//喚醒所有消費者
notifyAll();
}
}
/**
* 消息端 消費消息
*/
public synchronized void accept() {
//判斷通道是否有消息
if (init_capacity>0) { //通道有消息
//彈出消息
System.out.println(Thread.currentThread().getName()+":消費消息:"+" 庫存容量:"+(--init_capacity));
//消費完喚醒生產者 生產消息
notifyAll();
}else { //通道無消息
try {
System.out.println("庫存不足,等待生產者生產消息...");
//等待消費
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Producer生產者
package com.java.test;
/**
* 生產者
* @author jiajie
*
*/
public class Producer implements Runnable{
private MiddlewareChannel middlewareChannel;
private String threadName;
private String message;
/**
* 構造通道類
* @param middlewareChannel
*/
public Producer(MiddlewareChannel middlewareChannel) {
this.middlewareChannel = middlewareChannel;
}
/**
* 生產消息
*/
@Override
public void run() {
// TODO Auto-generated method stub
// while (true) {
// System.out.println(Thread.currentThread().getName());
// middlewareChannel.send(message);
// }
for (int i = 0; i < 20; i++) {
// System.out.println(Thread.currentThread().getName());
middlewareChannel.send();
}
}
}
Conumer消費者
package com.java.test;
import javax.sound.midi.MidiChannel;
/**
* 消費者
* @author jiajie
*
*/
public class Conumer implements Runnable{
private MiddlewareChannel middlewareChannel;
public Conumer(MiddlewareChannel middlewareChannel) {
this.middlewareChannel = middlewareChannel;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
// System.out.println(Thread.currentThread().getName());
middlewareChannel.accept();
}
}
}
測試
package com.java.test;
public class ClientTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//創建消息通道
MiddlewareChannel middlewareChannel = new MiddlewareChannel();
//創建消息消費者
Conumer conumer1 = new Conumer(middlewareChannel);
new Thread(conumer1,"消費者1").start();
// //創建消息消費者
// Conumer conumer2 = new Conumer(middlewareChannel);
// new Thread(conumer2, "消費者2").start();
//創建消息生產者1
Producer producer1 = new Producer(middlewareChannel);
new Thread(producer1,"生產者1").start();
// //創建消息生產者2
// Producer producer2 = new Producer(middlewareChannel, "我愛加班");
// new Thread(producer2,"生產者2").start();
}
}