zoukankan      html  css  js  c++  java
  • java多线程(7)---Condition

    Condition

    一、Condition概述

           在线程的同步时可以使一个线程阻塞而等待一个信号,同时放弃锁使其他线程可以能竞争到锁。

           在synchronized中我们可以使用Object的wait()和notify方法实现这种等待和唤醒。

           在Lock可以实现相同的功能就是通过Condition。Condition中的await()和signal()/signalAll()就相当于Object的wait()和notify()/notifyAll()。

    除此之外,Condition还是对多线程条件进行更精确的控制。notify()是唤醒一个线程,但它无法确认是唤醒哪一个线程。 但是,通过Condition,就能明确的指定唤醒读线程。

    二、Condition和Object案例对比

           案例说明:生成者在仓库满时,进入等待状态,同时唤醒消费者线程,消费者在仓库为空时,进入等待。同时唤醒生产者线程。

    1、采用await()和signal()方式

    (1)测试类

    public class ConditionLockTest {
    
        public static void main(String[] args){
    
            //相当于仓库
            Depot depot=new Depot();
            
          //创建两个生产者一个消费者
            Producer producer1=new Producer(depot);
            Producer producer2=new Producer(depot);
            Consumer consumer1=new Consumer(depot);
            
          //采用线程池方式
            Executor executors=Executors.newFixedThreadPool(5);
            executors.execute(producer1);
            executors.execute(producer2);
            executors.execute(consumer1);
        }
    }
    
    //生产者
    class Producer implements  Runnable {
    
        Depot depot;
        public Producer(Depot depot){
            this.depot=depot;
        }
        public void  run(){
         while(true){
            depot.prod();
           }
        }
    }
    
    //消费者
    class Consumer implements  Runnable{
        
        Depot depot;  
        public Consumer(Depot depot){
            this.depot=depot;
        }
        public void run(){
         while(true){
            depot.consum();
          }
       }
    }

    (2)仓库类

    public class Depot {
       //初始仓库为0,最大为10,超过10生产者停止生产
        private int size;
        private int maxSize=10;
    
        private Condition prodCondition;
        private Condition consumCondition;
    
        private Lock lock;
        public Depot(){
    
            this.size=0;
            this.lock=new ReentrantLock();
            //可以看出Condition对象依赖于Lock锁
            this.prodCondition=this.lock.newCondition();
            this.consumCondition=this.lock.newCondition();
        }
    
        /*
         * 生产者生产方法
         */
        public void prod(){
    
            lock.lock();
            try{
              //如果生产超过max值,则生产者进入等待
                while(size+1>maxSize){
                    try {
                        System.out.println(Thread.currentThread().getName()+"生产者进入等待状态");
                        prodCondition.await();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                size+=1;        
                System.out.println(Thread.currentThread().getName()+" 生产了一个 "+1+" 总共还有 "+size);
                
                //唤醒消费者线程
                consumCondition.signal(); 
    
            }finally {
                lock.unlock();
            }
        }
    
        /*
         * 消费者消费方法
         */
        public void consum(){
    
            lock.lock();
            try{
                //如果当前大小减去要消费的值,如果小于0的话,则进入等待
                while(size-1<0){
                    try {
                         System.out.println(Thread.currentThread().getName()+" 消费者进入等待状态");
                        consumCondition.await();
                       
    
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
    
                size-=1;
                System.out.println(Thread.currentThread().getName()+" 消费者消费了 "+1+" 个,总共还有 "+size);
                //唤醒生产者线程
                prodCondition.signal(); 
            }finally {
                lock.unlock();
            }
        }
    }

    运行结果(截取部分图)

    根据结果分析可以得出:
          生产者生产产品,当超过10个,生产者会处于等待状态,直到消费者消费者消费了一个产品,生产者才会重新唤醒。

     2、采用wait()和notifyAll()方法

     (1)仓库类代码(测试类代码不变)

    public class Depot {
       //初始仓库为0,最大为10,超过10生产者停止生产
        private int size;
        private int maxSize=10;
    
        public Depot(){
            this.size=0;
        }
    
        /*
         * 生产者生产方法
         */
        public synchronized void prod(){
    
            try{
              //如果生产超过max值,则生产者进入等待
                while(size+1>maxSize){
                    try {
                   //采用wait方法
                          wait();
                       System.out.println(Thread.currentThread().getName()+"生产者进入等待状态");         
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
    
                size+=1;        
                System.out.println(Thread.currentThread().getName()+" 生产了一个 "+1+" 总共还有 "+size);
                
                //唤醒所有线程
                 notifyAll();
             
            }finally {     
            }
        }
    
        /*
         * 消费者消费方法
         */
        public synchronized void consum(){
    
            try{
                //如果当前大小减去要消费的值,如果小于0的话,则进入等待
                while(size-1<0){
                    try {
                         wait();
                         System.out.println(Thread.currentThread().getName()+" 消费者进入等待状态");
                      
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
              
                size-=1;
                System.out.println(Thread.currentThread().getName()+" 消费者消费了 "+1+" 个,总共还有 "+size);
                //唤醒所有线程
                notifyAll();
              
            }finally {
            }
        }
    }    

    运行结果:

    对比:

           首先可以看出两个都可以实现生产者消费者的工作,不过可以发现Condition的signal相对于Object的notify最大有点就是它可以唤醒指定的线程,

    比如这里可以指定唤醒生产线程或者消费线程,而用notify是不能唤醒指定线程的,你只能通过notifyAll来唤醒所有。

     想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。少校【14】

  • 相关阅读:
    时间加减天数
    时间加减秒数
    什么BOM?
    js 事件基础
    js 九九乘法
    CSS3 动画基础单词语法
    css3 3D转换 基础语法
    css3 2D 转换 基础语法
    js onchange案例
    js之冒泡排序
  • 原文地址:https://www.cnblogs.com/qdhxhz/p/9206076.html
Copyright © 2011-2022 走看看