zoukankan      html  css  js  c++  java
  • 显式锁(四)Lock的等待通知机制Condition

       任意一个Java对象,都拥有一组监视器方法(定义在根类Object上),主要包括:wait( )、wait(long timeout)、notify()、notifyAll()方法;这些方法与关键字synchronized结合使用,可以实现 隐式锁的等待/通知机制。而显示锁Lock也实现了等待/通知机制;Condition接口也提供了类似Object的监视器方法,与Lock配合使用可以实现 显式锁的等待/通知机制,但是两者在使用方式和功能特性有所差别。总得来说,Condition接口更加灵活,功能更多:

    • Condition 接口是支持多个等待队列,也称为条件队列,即根据不同的条件进入不同的等待队列,相应的,用户便可以只在指定的等待队列上唤醒线程,而不是唤醒所有的线程。而 Object监视器 则只能有一个等待队列。
    • Condition 接口还提供了对中断不敏感的等待方法,即当处于等待状态时,是不会被中断的。而Object监视器 不支持不可中断的等待。
    • Condition 接口除了提供了超时等待方法之外,还提供了等待直到将来某个时间段的方法;Object监视器只有超时等待的方法。

    Condition 接口的方法:

    方法名称 描 述
    void await() throws InterruptedException 造成当前线程在接到通知或被中断之前一直处于等待状态。即发生以下两种情况,将会从await()方法返回:
    1、其他某个线程调用此 Condition 的 signal()、signalAll()方法;
    2、其他某个线程中断当前线程
    void awaitUninterruptibly() 造成当前线程在接到通知之前一直处于等待状态。 与await()方法相比,这是不可中断的等待方法
    long awaitNanos(long nanosTimeout) throws InterruptedException 造成当前线程在接到通知、被中断或到达指定等待时间之前一直处于等待状态。
    返回值:此方法返回时,距离超时的剩余时间,即返回值就是(nanosTimeout - 实际耗时);如果返回值是0或者负数,那么认定已经超时
    boolean await(long time, TimeUnit unit) throws InterruptedException 造成当前线程在接到通知、被中断或到达指定等待时间之前一直处于等待状态。
    返回值:如果在从此方法返回前检测到等待时间超时(到达指定时间),则返回 false,否则返回 true
    此方法在行为上等效于: awaitNanos(unit.toNanos(time)) > 0
    boolean awaitUntil(Date deadline) throws InterruptedException 造成当前线程在接到通知、被中断或到达指定最后期限之前一直处于等待状态。
    返回值:如果在从此方法返回前检测到等待时间超时(到达指定时间),则返回 false,否则返回 true
    void signal() 唤醒一个等待线程。如果所有的线程都在等待此条件,则选择其中的一个唤醒。在从 await 返回之前,该线程必须重新获取锁。
    void signalAll() 唤醒所有等待线程。 如果所有的线程都在等待此条件,则唤醒所有线程。在从 await 返回之前,每个线程都必须重新获取锁。

    @ Example Condition 的例子

    public class BoundedQueue<T> {
    	private Object[] item;
    	//添加的下标、删除的下标、数组的当前数量
        private int addIndex,removeIndex,count;
        private Lock lock = new ReentrantLock();
        private Condition notFull = lock.newCondition();
        private Condition notEmpty = lock.newCondition();
        
        public BoundedQueue(int size){
        	item = new Object[size];
        }
        
        //添加一个元素,如果数组满,则添加线程进入等待状态,直到有空位
        public void add(T t) throws InterruptedException{
        	lock.lock();
        	try{
        		while(count == item.length){
        			//可中断的等待,如果没有剩余空间,那么就进入notFull的等待队列
        			notFull.wait();
        		}
        		item[addIndex] = t;
        		if(++addIndex == item.length){//模拟环数组,一直插入,直到尾部,又重新从头部插入
        			addIndex = 0;
        		}
        		count++;
        		//刚插入一个元素,不为空的条件满足,可唤醒等待在notEmpty队列上的线程
        		notEmpty.signal();
        	}finally {
    			lock.unlock();
    		}
        }
        
        //从头部移除一个元素,如果数组为空,则等待,直到数组不为空
        public T remove(){
        	lock.lock();
        	try{
        		while(count == 0){
        			//不可中断的等待,不为空的条件不满足,就会一直等待
        			notEmpty.awaitUninterruptibly();;
        		}
        		Object x = item[removeIndex];
        		if(++removeIndex == item.length){
        			removeIndex = 0;
        		}
        		count--;
        		//刚移除一个元素,数组没有满的条件符合,唤醒等待在notFull上的线程
        		notFull.signal();
        		return (T)x;
        	}finally{
        		lock.unlock();
        	}
        }
    }
    
  • 相关阅读:
    排序希尔排序
    Sentinel 限流
    排序基数排序
    【ProToolkit范例之三】遍历模型下的所有Feature
    【ProToolkit范例之四】创建udf
    【ProToolkit范例之五】输出Asm的架构
    鼠标滚轮改变文本框值的jQuery插件cutePsWheel发布
    自己做手做“分享到”小工具
    深入理解jQuery AJAX调用页面内Web服务
    没错,你没有看错,博客园Android客户端开源了!
  • 原文地址:https://www.cnblogs.com/jinggod/p/8491259.html
Copyright © 2011-2022 走看看