生产者消费者 java.util.concurrent.lock包

package com.mozq.thread.producer2;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 *     当使用等待时
 *     如果用if会造成,线程被唤醒时不管条件是否满足,都会执行任务代码。产生错误。
 *     改用while,每次线程被唤醒时会进行条件判断,是否满足。但是产生了死锁问题。
 *     1.通过使用notifyAll而不是notify方法来解决死锁。
 *     单生产者和单消费者不会因使用while发生死锁,因为,线程池中只有 一个另一方的线程,notify方法必然会唤醒另一方的线程。
 *     多生产者和多消费者的等待集中有生产方和消费方的线程,notify方法可能会唤醒本方线程而不是另一方,造成 死锁。
 *     
 *     Condition对象可以为表示锁的一个等待集,一个锁可以产生多个Condition对象也就是等待集。并对它们分别进行操作。
 *     针对多生产者和多消费者,我们可以分别为生产者和消费者创建一个等待集,并在唤醒时,调用另一方等待集的通知,确保唤醒的是另一方线程。避免了死锁。
 * 
 * @author jie
 *
 */
class Resource{
    private String name = null;
    private int count = 0;
    private boolean set = false;
    private Lock lock = new ReentrantLock();
    private Condition producer = lock.newCondition();
    private Condition consumer = lock.newCondition();
    
    public void set(String name) {
        lock.lock();
        try {
            //如果已经存在资源,等待
            while(set) {
                try {
                    producer.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //没有资源就创建
            count++;
            this.name = name + count;
            System.out.println(Thread.currentThread().getName() + "生产。"+ this.name);
            set = true;
            //同时消费者消费
            consumer.signal();
        }finally {
            lock.unlock();
        }
    }
    
    public void out() {
        lock.lock();
        try {
            //如果没有产品,等待
            while(!set) {
                 try {
                     consumer.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //有就消费
            System.out.println(Thread.currentThread().getName() + "消费。。。。。"+ this.name);
            set = false;
            //通知生产者生产
            producer.signal();
        } finally {
            lock.unlock();
        }
    }
}

class Input implements Runnable{
    private Resource r;
    public Input(Resource r) {
        this.r = r;
    }

    @Override
    public void run() {
        while(true) {
            r.set("烤鸡");
        }
    }
    
}
class Output implements Runnable{
    private Resource r;
    public Output(Resource r) {
        this.r = r;
    }
    
    @Override
    public void run() {
        while(true) {
            r.out();
        }
    }
    
}

public class ProducerConsumerDemo {
    public static void main(String[] args) {
        //创建资源
        Resource r = new Resource();
        //创建任务
        Input in = new Input(r);
        Output out = new Output(r);
        //创建线程
        Thread t0 = new Thread(in);
        Thread t1 = new Thread(in);
        Thread t2 = new Thread(out);
        Thread t3 = new Thread(out);
        //开启线程
        t0.start();
        t1.start();
        t2.start();
        t3.start();
    }
}
原文地址:https://www.cnblogs.com/mozq/p/10411089.html