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();
}
}