zoukankan      html  css  js  c++  java
  • 生产者消费者 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();
        }
    }
  • 相关阅读:
    主进程与渲染进程的异同
    Electron node integration enabled 设置
    JS-函数总结
    JS-变量、作用域、垃圾回收机制总结
    python进阶知识笔记
    高级抽象函数
    mac支持的文件系统
    生成器generator & 迭代器iterator
    磁盘如何做才能让系统识别
    winPE盘能做什么
  • 原文地址:https://www.cnblogs.com/mozq/p/10411089.html
Copyright © 2011-2022 走看看