前言:先说一个坑了我大半天的教训啊,不同的线程之间企图用notify和wait来配合,这就大错特错了!!!下面我们来理解思考一下
因为wait nofity都是native方法 源码观看的意义不大,所以要好好看注释
源码中这个注释一语道破天机!! 就是我们谁wait()了 就要谁来notify来激活 而我们前言中说的那个错误分别是在两个线程中的,所以。。。。是不能够互相wait() notify的
看似这个解释和小错误简单,实则不好好看源码的注释也很懵,贴在这里防止大家走弯路
下面用wait notify来实现一个生产者消费者的模型,代码如下,运行结果在后面
/**
* 消费者
*/
public class Consume implements Runnable{
Product product;
int i = 0;
Consume(){
}
Consume(Product product){
this.product = product;
}
@Override
public void run() {
while (true){
if(product.stopProduce==true&&product.list.size()==0){
product.consumeProduct();//退出之前激活另一个Consume
break;
}
if(product.consumeProduct()){
System.out.println(Thread.currentThread().getName()+"消费者消费元素"+"stopProduct="+product.stopProduce);
}else{
}
i++;//这个i不是线程安全的 不过无所谓 我们这里是为了让消费者出去
if(i==200){
product.consumeProduct();//退出之前激活另一个Consume
break;
}
}//while
System.out.println("消费者"+Thread.currentThread().getName()+"退出-------------------》");
System.out.println("还剩商品的数量是:"+product.list.size());
}
}
/**
* 生产者
*/
class Producer implements Runnable{
Product product;
int i = 0;
Producer(Product product){
this.product = product;
}
Producer(){
}
@Override
public void run() {
while(true){
int p = (int) (Math.random()*10);
boolean flag = product.addProduct(p);
if(flag==true){
i++;
}else{
System.out.println("生产队列满了");
}
if(i==200)//如果生产了200次就停止退出
{
product.stopProduce=true;
break;
}
}//while
System.out.println("生产者退出------------------------>");
}
}
import java.util.ArrayList;
import java.util.List;
/**
* * 下面是一个消费的队列
* * num是当前队列维护的长度
* * list 是我们实际的队列
*/
public class Product {
int num = 10;
int consumeProduct=0;
boolean stopProduce = false;
List<Integer> list = new ArrayList<>();
/**
* true 加入成功
* false 加入不成功
*/
synchronized public boolean addProduct(Integer e){
if(list.size()<num){
System.out.println("生产者生产元素"+e);
list.add(e);
System.out.println("当前生产的数量="+list.size());
return true;
}
else{
try {
System.out.println("队列满了等待消费者消费,现在list的长度是"+list.size());
notify();//消费者消费激活另一个等待的消费者
wait();
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
return false;
}
}
/**
* true 消费成功
* false 消费失败
*/
synchronized public boolean consumeProduct(){
if(list.size()>0){
int index = list.size()-1;
consumeProduct=list.get(index);
System.out.println("消费前现在list的长度是"+list.size());
System.out.println("消费的元素是:"+consumeProduct);
list.remove(index);
System.out.println("消费后现在list的长度是"+list.size());
notify();//激活另一个消费者
return true;
}else{
notify();//激活生产者 但也可能激活另一个消费者
System.out.println("通知生产者生产");
try {
if(stopProduce==false){
System.out.println("消费者等待");
wait();
}else{
System.out.println("停止生产,消费者已经消费完成");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return false;
}
}
}
//生产者消费者模型
public class MyTest3 {
public static void main(String[] args) throws InterruptedException {
Product product = new Product();
new Thread(new Consume(product),"c1").start();
new Thread(new Consume(product),"c2").start();
new Thread(new Producer(product),"p").start();
}
}
部分结果:
消费的元素是:2
消费后现在list的长度是3
c1消费者消费元素stopProduct=false
消费前现在list的长度是3
消费的元素是:9
消费后现在list的长度是2
c2消费者消费元素stopProduct=false
消费前现在list的长度是2
消费的元素是:4
消费后现在list的长度是1
c2消费者消费元素stopProduct=false
消费前现在list的长度是1
消费的元素是:3
消费后现在list的长度是0
c1消费者消费元素stopProduct=false
生产者生产元素7
当前生产的数量=1
消费前现在list的长度是1
消费的元素是:7
消费后现在list的长度是0
c1消费者消费元素stopProduct=false
通知生产者生产
消费者等待
通知生产者生产
消费者等待
生产者生产元素4
当前生产的数量=1
生产者生产元素1
当前生产的数量=2
生产者生产元素1
当前生产的数量=3
消费前现在list的长度是3
消费的元素是:1
消费后现在list的长度是2
c2消费者消费元素stopProduct=false
消费前现在list的长度是2
消费的元素是:1
消费后现在list的长度是1
c1消费者消费元素stopProduct=false
生产者生产元素7
当前生产的数量=2
消费前现在list的长度是2
消费的元素是:7
消费后现在list的长度是1
c1消费者消费元素stopProduct=false
消费前现在list的长度是1
消费的元素是:4
消费后现在list的长度是0
c2消费者消费元素stopProduct=false
通知生产者生产
消费者等待
生产者生产元素6
当前生产的数量=1
消费前现在list的长度是1
消费的元素是:6
消费后现在list的长度是0
生产者退出------------------------>
通知生产者生产
停止生产,消费者已经消费完成
消费者c1退出-------------------》
还剩商品的数量是:0
c2消费者消费元素stopProduct=true
通知生产者生产
停止生产,消费者已经消费完成
消费者c2退出-------------------》
还剩商品的数量是:0
Process finished with exit code 0