【JAVA核心知识】22-F.1:Condition的简单使用

目录

前言

Condition的方法介绍

示例代码

关联导航 


前言

21-F.1:ReentrantLock的简单使用介绍了ReentrantLock的简单使用,可以简单的认为ReentrantLock是功能更加全面的synchronized的API形式。那么ReentrantLock的阻塞(synchronized的wait)和唤醒(synchronized的notify)如何实现呢,此时就需要和ReentrantLock一样在JDK 1.5引入的Condition出马了,相较于Object的wait(),notify()方法,Condition具有更全面的功能。

可以通过ReentrantLock.newCondition()来获得一个Condition实例,Condition与ReentrantLock绑定,持有绑定ReentrantLock的线程才能通过Condition进行阻塞和唤醒。不同于synchronized使用lockObj的wait(),notify()方法仅有一个等待队列,一个ReentrantLock可以绑定有多个Condition,即可以设置多个等待队列。一个Condition代表一个通信通道,但是要注意每个Condition的等待指令只能由同一个Condition唤醒。不同Condition之间是无法交叉唤醒的(见代码ConditionDemo)。

Condition的方法介绍

  • await():阻塞等待,等效于wait()
  • await(long time, TimeUnit unit):阻塞等待指定时间,指定时间后自动唤醒开始竞争锁
  • awaitNanos(long nanosTimeout): 纳秒级别的阻塞等待指定时间,指定时间后自动唤醒开始竞争锁
  • awaitUntil(Date deadline):阻塞等待到某一日期,到达deadline时自动唤醒开始竞争锁
  • awaitUninterruptibly():无中断的等待,在这个等待状态下,此线程会无视对他的中断指令
  • signal():唤醒一个阻塞的线程,等效于notify()。
  • signalAll():唤醒所有阻塞的线程,等效于notifyAll()

注意Condition也是有wait()和notify()方法的,这是因为wait()和notify()是属于Object的,而任何类都继承了Object。但是wait()和notify()并不属于Condition提供的功能,将Condition作为一个普通的锁对象使用synchronized时他们才有用。因此切记不要用await()等待了却想用notify()唤醒,是唤醒不了的,他们本身就不是一套。await和signal结合使用,wait和notify结合使用。

示例代码

public class ConditionDemo {

    public static void main(String[] args) {
        final ReentrantLock lock = new ReentrantLock();
        final Condition c = lock.newCondition();

        /*---------------多个线程之间的相互唤醒------------------*/
        /**
        for (int i = 0; i < 5; i++) {
            final int j = i;
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        lock.lock();
                        System.out.println(j + "拿到锁");
                        System.out.println(j + "开始等待");
                        c.await(); 
                        System.out.println(j + "收到信号");
                        System.out.println(j + "发出信号");
                        c.signal();
                    } catch (Exception e) {
                        System.out.println("2error");   
                        e.printStackTrace();   
                    } finally {
                        lock.unlock(); // 一定记得要解锁!!!
                    }
                }
            });
            t.start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        lock.lock();
        System.out.println("主线程拿到锁");
        System.out.println("主线程发出信号");
        // 唤醒是signal不是notify,notify是使用关键字synchronized时的唤醒方法!!!
        //  使用notify会抛java.lang.IllegalMonitorStateException异常
        c.signal();   // 唤醒,默认优先唤醒先等待的线程
//        c.signalAll();    // 唤醒全部         
        System.out.println("主线程释放锁");
        lock.unlock();
        **/
        /*---------------多个线程之间的相互唤醒------------------*/
        
        /*---------------几种等待机制------------------*/
        /**
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    lock.lock();
                    System.out.println("1拿到锁");
                    System.out.println("1等待开始");
//                    c.await();    // 等待
//                    c.await(1, TimeUnit.SECONDS); //等待1s, 1s后解除等待开始竞争资源
//                    c.awaitNanos(1000L);// 等待1000纳秒  
//                    c.awaitUntil(new Date(new Date().getTime() + 1000)); // 等待到某一日期
                    c.awaitUninterruptibly();   // 无中断的等待,在这个等待状态下,此线程会无视对他的中断指令
                    System.out.println("1被唤醒");
                } catch (Exception e) {
                    System.out.println("1error");
                    e.printStackTrace();
                } finally {
                    lock.unlock(); 
                }
            }
        });

        t1.start();
        try {
            Thread.sleep(1000);  // 等待1s确保t1进入等待状态,避免主线程先抢到资源执行完毕后t1得到资源才开始等待
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.interrupt();  // awaitUninterruptibly时这个语句被无视,其它等待下会抛异常java.lang.InterruptedException
        lock.lock();
        System.out.println("主线程拿到锁");
        System.out.println("主线程发出信号");
        c.signal(); // 唤醒
        lock.unlock(); // 释放锁
        **/
        /*---------------几种等待机制------------------*/
      
      

      /*-----线程3用以验证睡眠是否释放锁及验证Condition之间无法相互唤醒-----*/
      /**
        Thread t3 = new Thread(new Runnable() {
          @Override
          public void run() {
              try {
                  lock.lock();
                  System.out.println("3拿到锁");
                  System.out.println("3开始等待");
                  c.await();
                  System.out.println("3收到信号");
              } catch (Exception e) {
                  System.out.println("3error");   
                  e.printStackTrace();   
              } finally {
                  lock.unlock();
              }
          }
      });
      */
      /*-----线程3用以验证睡眠是否释放锁及验证Condition之间无法相互唤醒-----*/


      /*--------线程持有锁并睡眠时间是不会释放资源(锁)的------------*/
        /**
      lock.lock();
      t3.start();
      System.out.println("主线程拿到锁");
      System.out.println("主线程开始睡眠");
        try {
            Thread.sleep(1000); // 线程持有锁并睡眠时间是不会释放资源(锁)的
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
       System.out.println("主线程睡眠结束");
       lock.unlock();
       */
       /*--------线程持有锁并睡眠时间是不会释放资源(锁)的------------*/
       
       /*---------------不同Condition之间无法相互唤醒------------------*/
        /**
      final Condition c2 = lock.newCondition();
      try {
          Thread.sleep(1000);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
        lock.lock();
//        c.signalAll();
        c2.signalAll(); // c2并不能唤醒c的等待线程
        lock.unlock();
        */
        /*---------------不同Condition之间无法相互唤醒------------------*/
    }

}

关联导航 

【JAVA核心知识】系列导航 [持续更新中…]
关联导航:21-F.1:ReentrantLock的简单使用
关联导航:22:从源码看ReentrantLock的Condition
欢迎关注…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yue_hu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值