java中重入ReentrantLock(Condition监视器)锁生产者消费者

来源:互联网 发布:线切割报价软件 编辑:程序博客网 时间:2024/05/23 15:45
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


/*


 本程序致力于解决多出现多个生产者,多个消费者的时候,依然能够达到生产一次,消费一次的功能
 :
 解决的方法就是:1)在被唤醒之后仍然进行条件判断,去检查要改的数字是否满足条件,如果不满足条件就继续睡眠。把两个方法中的if改为while即可。
 当然,此时仍会出现问题,就是所以线程都等待,失去资格
 2)需要将notify()改成notifyAll()


 升级版:
 使用Lock来替换synchronized,wait,notify,nonifyAll语法和语句的使用
 不需要同步,不需要notify
 ------------
 加强升级版:
 此版本为最终版,主要在使用锁lock的基础上,加上唤醒对方(不包括己方)进程的优化
 通过一个锁建立多个condition对象来解决


 流程:
 生产者拿到锁,执行,判断没有真,继续执行,生产完毕后唤醒消费者来消费    生产者唤醒消费者
 消费者拿到锁,执行,判断没有假,继续执行,消费完毕后唤醒生产者继续生产   消费者唤醒生产者


 */
public class ShengChanXiaoFeiZhe {
    public static void main(String[] args) {
        Resources r = new Resources();
        Productor pro = new Productor(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();
        System.out.println("Hello World!");
    }
}


class Resources {//相当于仓库  消费者在仓库中消耗(out)  生产者向仓库中添加(set)
    private String name;
    private int count = 1;
    private boolean flag = false;
    private Lock lock = new ReentrantLock();


    private final int max = 1; //仓库大小
    private int temp = 0; //仓库已经使用多少
    private Condition condition_pro = lock.newCondition(); //使用lock建立生产者的condition对象
    private Condition condition_con = lock.newCondition(); //使用lock建立消费者的condition对象


    public void set(String name) throws InterruptedException {//生产者向仓库中添加
        lock.lock();
        try {
            //1)循环判断
            while (flag)
                //如果为真,放弃生产者的资格
                condition_pro.await(); //会抛出异常

            this.name = name + "--" + count++;
            System.out.println(Thread.currentThread().getName() + "生产者" + this.name);
            temp += 1;
            if (temp == max) {//仓库已经满了
                flag = true;
            }
            //2)使用消费condition唤醒进程
            condition_con.signal(); //生产者生产完毕后,唤醒消费者的进程(不再是signalAll)
        } finally {
            lock.unlock();
        }


    }


    public void out() throws InterruptedException { //消耗仓库中商品
        lock.lock();
        try {
            //1)循环判断
            while (!flag)
                //如果为假,放弃消费者的资格
                condition_con.await();



            System.out.println(Thread.currentThread().getName() + " ....消费者...." + this.name);
            temp -= 1;
            if (temp ==0) {//仓库空了
                flag = false;
            }
            //2)使用生产者condition唤醒进程
            condition_pro.signal(); //消费者消费完毕后,唤醒生产者的进程
        } finally //防止当前线程拿到锁后抛异常一直不释放锁
        {
            lock.unlock();
        }


    }
}


class Productor implements Runnable {
    private Resources res;


    Productor(Resources res) {
        this.res = res;
    }


    public void run() {
        while (true) {
            try {
                res.set("++商品++"); //需要抛出异常
            } catch (InterruptedException e) {
            }


        }
    }


}


class Consumer implements Runnable {
    private Resources res;


    Consumer(Resources res) {
        this.res = res;
    }


    public void run() {
        while (true) {
            try {
                res.out(); //需要抛出异常
            } catch (InterruptedException e) {
            }


        }
    }


}
阅读全文
0 0
原创粉丝点击