zoukankan      html  css  js  c++  java
  • Java多线程系列---“JUC锁”03之 Condition

    转自:http://www.cnblogs.com/skywang12345/p/3496716.html (含部分修改)

    概要

    前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:
    Condition介绍
    Condition函数列表
    Condition示例

    Condition介绍

    Condition的作用是对锁进行更精确的控制。Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法。不同的是,Object中的wait(),notify(),notifyAll()方法是和"同步锁"(synchronized关键字)捆绑使用的;而Condition是需要与"互斥锁"/"共享锁"捆绑使用的。

    Condition函数列表

    复制代码
    // 造成当前线程在接到信号或被中断之前一直处于等待状态。
    void await()
    // 造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
    boolean await(long time, TimeUnit unit)
    // 造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
    long awaitNanos(long nanosTimeout)
    // 造成当前线程在接到信号之前一直处于等待状态。
    void awaitUninterruptibly()
    // 造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。
    boolean awaitUntil(Date deadline)
    // 唤醒一个等待线程。
    void signal()
    // 唤醒所有等待线程。
    void signalAll()
    复制代码

    Condition示例

    示例1是通过Object的wait(), notify()来演示线程的休眠/唤醒功能。
    示例2是通过Condition的await(), signal()来演示线程的休眠/唤醒功能。

    示例1

    复制代码
    public class WaitTest1 {
    
        public static void main(String[] args) {
    
            ThreadA ta = new ThreadA("ta");
    
            synchronized(ta) { // 通过synchronized(ta)获取“对象ta的同步锁”,(是当前线程,即main获取了锁ta)
                try {
                    System.out.println(Thread.currentThread().getName()+" start ta");
                    ta.start();
    
                    System.out.println(Thread.currentThread().getName()+" block");
                    ta.wait();    // 等待
    
                    System.out.println(Thread.currentThread().getName()+" continue");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        static class ThreadA extends Thread{
    
            public ThreadA(String name) {
                super(name);
            }
    
            public void run() {
                synchronized (this) { // 通过synchronized(this)获取“当前对象的同步锁”
                    System.out.println(Thread.currentThread().getName()+" wakup others");
                    notify();    // 唤醒“当前对象上的等待线程”
                }
            }
        }
    }
    复制代码

    示例2

    复制代码
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class ConditionTest1 {
            
        private static Lock lock = new ReentrantLock();
        private static Condition condition = lock.newCondition();
    
        public static void main(String[] args) {
    
            ThreadA ta = new ThreadA("ta");
    
            lock.lock(); // 获取锁
            try {
                System.out.println(Thread.currentThread().getName()+" start ta");
                ta.start();
    
                System.out.println(Thread.currentThread().getName()+" block");
                condition.await();    // 等待
    
                System.out.println(Thread.currentThread().getName()+" continue");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();    // 释放锁
            }
        }
    
        static class ThreadA extends Thread{
    
            public ThreadA(String name) {
                super(name);
            }
    
            public void run() {
                lock.lock();    // 获取锁
                try {
                    System.out.println(Thread.currentThread().getName()+" wakup others");
                    condition.signal();    // 唤醒“condition所在锁上的其它线程”
                } finally {
                    lock.unlock();    // 释放锁
                }
            }
        }
    }
    复制代码

    运行结果:(上面两个例子的运行结果都是这个)

    main start ta
    main block
    ta wakup others
    main continue

    通过“示例1”和“示例2”,我们知道Condition和Object的方法有一下对应关系:

                  Object      Condition  
    休眠          wait        await
    唤醒个线程     notify      signal
    唤醒所有线程   notifyAll   signalAll

    Condition除了支持上面的功能之外,它更强大的地方在于:能够更加精细的控制多线程的休眠与唤醒。对于同一个锁,我们可以创建多个Condition,在不同的情况下使用不同的Condition。
    例如,假如多线程读/写同一个缓冲区:当向缓冲区中写入数据之后,唤醒"读线程";当从缓冲区读出数据之后,唤醒"写线程";并且当缓冲区满的时候,"写线程"需要等待;当缓冲区为空时,"读线程"需要等待。         如果采用Object类中的wait(), notify(), notifyAll()实现该缓冲区,当向缓冲区写入数据之后需要唤醒"读线程"时,不可能通过notify()或notifyAll()明确的指定唤醒"读线程",而只能通过notifyAll唤醒所有线程(但是notifyAll无法区分唤醒的线程是读线程,还是写线程)。  但是,通过Condition,就能明确的指定唤醒读线程。

    //TODO

    后面会补充Condition结合消费者生产者模式例子。

  • 相关阅读:
    centos7 hadoop 2.8安装
    centos7安装jdk1.8
    kafka安装测试报错 could not be established. Broker may not be available.
    中文乱码总结之JSP乱码
    分布式作业笔记
    <c:forEach var="role" items="[entity.Role@d54d4d, entity.Role@1c61868, entity.Role@6c58db, entity.Role@13da8a5]"> list 集合数据转换异常
    Servlet.service() for servlet [jsp] in context with path [/Healthy_manager] threw exception [Unable to compile class for JSP] with root cause java.lang.IllegalArgumentException: Page directive: inval
    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project triage: Compilation failure [ERROR] No compiler is provided in this environment.
    Invalid bound statement (not found): com.xsw.dao.CategoryDao.getCategoryById] with root cause
    org.apache.ibatis.binding.BindingException: Parameter 'start' not found. Available parameters are [1, 0, param1, param2]
  • 原文地址:https://www.cnblogs.com/Hermioner/p/9932160.html
Copyright © 2011-2022 走看看