1.多线程-线程间通信-多生产者多消费者问题
多生产者和多消费者。等待唤醒机制。
产生了两个问题:
1.出现了多次连续生产,未消费,或者一个商品被消费多次。
解决:必须要--------每一个被唤醒的线程判断一次标记,所以将if判断改为while判断。
2.出现了死锁。
本方唤醒了本方,导致了所有的线程都等待了。
解决方式就是:唤醒所有等待的线程。这样既唤醒了本方也唤醒对方。
虽然解决了多生产消费的问题,但是有些低效。
解决方法一: 唤醒所有等待的线程
class Resource{
private String name;//定义一个商品都有名字。
private int count = 1; //定义一个商品的编号。
private boolean flag = false;//定义用来判断是否有商品的标记。
public synchronized void set(String name){
while(flag)
try{wait();}catch(Exception e){}//t1,t2
this.name = name+"--"+count;//蛋糕1 蛋糕2 蛋糕3
count++;
System.out.println(Thread.currentThread().getName()+"---生产了,"+this.name);
//生产蛋糕1 生产蛋糕2 生产蛋糕3
flag = true; //将标记改为true。
notifyAll();//唤醒等待的线程。
}
public synchronized void get()//{
while(!flag)
try{wait();}catch(Exception e){}//t3.t4
System.out.println(Thread.currentThread().getName()+"-------消费了....."+this.name);//消费蛋糕1
flag = false;
notifyAll();
}
}
//定义生产者的任务。
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.set("蛋糕");
}
}
}
//定义消费者的任务。
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.get();
}
}
}
class ThreadDemo_Producer_Consumer2 {
public static void main(String[] args) {
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
//创建两个生产者线程。
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
//创建两个消费者线程。
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
解决方法二:使用Lock锁对象和Condition监听对象
根据jdk1.5 版本的特性,创建一个锁对象。比同步的隐式锁操作要更加的面向对象。提供了显示的锁操作。
通过lock锁获取监视器方法对象。Condition 负责生产者的监视操作。
再创建一个监视器方法对象。负责消费者的监视操作。
解决了低效的问题
import java.util.concurrent.locks.*;
class Resource{
//定义一个商品都有名字。
private String name;
//定义一个商品的编号。
private int count = 1;
//定义用来判断是否有商品的标记。
private boolean flag = false;
//根据jdk1.5 版本的特性,创建一个锁对象。比同步的隐式锁操作要更加的面向对象。提供了显示的锁操作。
final Lock lock = new ReentrantLock();//互斥锁。
//通过lock锁获取监视器方法对象。Condition 负责生产者的监视操作。
final Condition producer = lock.newCondition();
//再创建一个监视器方法对象。负责消费者的监视操作。
final Condition consumer = lock.newCondition();
public void set(String name)//{
//通过锁对象进行显示的获取锁操作。
lock.lock();//获取锁,锁的开始位置,想从哪里锁就把锁放在什么地方
try{
while(flag)
try{producer.await();}catch(Exception e){}//t1,t2
this.name = name+"--"+count;
count++;
System.out.println(Thread.currentThread().getName()+"生产了,"+this.name);
//将标记改为true。
flag = true;
consumer.signal();//唤醒等待的线程。
}finally{
//释放锁。
lock.unlock();//定义在finally中,要求一定被释放。
}
}
public void get()//{
lock.lock();
try{
while(!flag)
try{consumer.await();}catch(Exception e){}//t3.t4
System.out.println(Thread.currentThread().getName()+"--消费了."+this.name); //消费蛋糕1
flag = false;
producer.signal();
}finally{
lock.unlock();
}
}
}
//定义生产者的任务。
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.set("蛋糕");
}
}
}
//定义消费者的任务。
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.get();
}
}
}
class ThreadDemo_Producer_Consumer3 {
public static void main(String[] args) {
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
//创建两个生产者线程。
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
//创建两个消费者线程。
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
转载于:https://blog.51cto.com/pengya123/1774102