最简单的实现方式是利用阻塞队列,废话不多说,上代码:
wait、notify、notifyAll是Object对象的属性,并不属于线程。我们先解释这三个的一个很重要的概念
- wait:使持有该对象的线程把该对象的控制权交出去,然后处于等待状态,并释放锁
- notify:通知某个正在等待这个对象的控制权的线程可以继续运行,同样也是释放锁
- notifyAll:会通知所有等待这个对象控制权的线程继续运行
/**
* class_name: Main
* package: com.jacky.thread.producecomsumer
* describe: 利用队列实现产生者和消费者模式
* creat_user: Jacky
* creat_date: 2019/2/14
* creat_time: 上午10:30
**/
public class Main {
ArrayBlockingQueue<String> bq = new ArrayBlockingQueue<String>(10);
public void putData(String data) throws Exception {
bq.put(data);
}
public String getData() throws Exception {
String data = bq.take();
return data;
}
public static void main(String[] args) {
Main m = new Main();
new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (true) {
try {
Thread.sleep(100);
i++;
m.putData(String.valueOf(i));
System.out.println(Thread.currentThread().getName() + "完成生产编号" + i + "的产品");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
String data = m.getData();
System.out.println(Thread.currentThread().getName() + "消费了编号" + data + "的产品");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}
}
输出结果:
但是这样有点浪费性能,此时我们加入wait
、notify
,synchronized
,关键字实现同步批量消费
版本2:
/**
* class_name: Main2
* package: com.jacky.thread.producecomsumer
* describe: 批量消费
* creat_user: Jacky
* creat_date: 2019/2/14
* creat_time: 上午10:59
**/
public class Main2 {
private ArrayBlockingQueue<Integer> bq = new ArrayBlockingQueue<Integer>(10);
public void putData(Integer data){
try {
bq.put(data);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public Integer getData(){
try {
return bq.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
public Integer getQueueSize(){
return bq.size();
}
public static void main(String[] args) {
Main2 m2 = new Main2();
new Thread(new Runnable() {
@Override
public void run() {
int data= 0;
while(true){
synchronized (m2){
try {
Thread.sleep(200);
data++;
if(m2.getQueueSize() == 10){
System.out.println(Thread.currentThread().getName() + ": 停止生产,等待消费");
// m2.notifyAll();
m2.notify();
m2.wait();
}
m2.putData(data);
System.out.println(Thread.currentThread().getName() + ": 已生产编号" + data + "产品");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
synchronized (m2){
try {
Thread.sleep(200);
if(m2.getQueueSize() == 0){
// m2.notifyAll();
m2.notify();
m2.wait();
System.out.println(Thread.currentThread().getName() +": 等待通知消费");
}
Integer data = m2.getData();
System.out.println(Thread.currentThread().getName() + ": 已消费编号" + data+ "的产品");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}).start();
}
}
输出结果:
大功告成,完成一批次的生产再通知消费