当前位置: 首页 > news >正文

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结合消费者生产者模式例子。

转载于:https://www.cnblogs.com/Hermioner/p/9932160.html

相关文章:

  • Junit Test 的时候出错java.lang.IllegalStateException: Failed to load ApplicationContext
  • 小教练教MM如何去掉你的小肚子
  • vue cli 3 webpack-merge webpack 3 bug
  • 一句话介绍python线程、进程和协程
  • ASP.NET中上传并读取Excel文件数据
  • 在 ISA Server 2004 中发布 ××× 服务器
  • Linux Command
  • ACM-ICPC 2018 青岛赛区现场赛 D. Magic Multiplication ZOJ 4061 (思维+构造)
  • 实战 HTTP 处理程序(HTTP Handler) (4)--与Web程序共享Session
  • DOM事件流
  • 绝对路径 相对路径 相对虚拟目录路径
  • Oracle Long类型转换为Clob类型
  • 三维模型逐渐透明化
  • [转]奇文-闲话操作系统(1/4)
  • 如何得到需要下载文件的链接(路径)?
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • ➹使用webpack配置多页面应用(MPA)
  • ES6 ...操作符
  • tab.js分享及浏览器兼容性问题汇总
  • webpack4 一点通
  • win10下安装mysql5.7
  • 闭包--闭包之tab栏切换(四)
  • ------- 计算机网络基础
  • 前端性能优化——回流与重绘
  • 如何学习JavaEE,项目又该如何做?
  • 数组大概知多少
  • 线上 python http server profile 实践
  • 详解移动APP与web APP的区别
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • #Linux(Source Insight安装及工程建立)
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • #预处理和函数的对比以及条件编译
  • (1)(1.9) MSP (version 4.2)
  • (C++17) optional的使用
  • (C语言)逆序输出字符串
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (TOJ2804)Even? Odd?
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (附源码)计算机毕业设计大学生兼职系统
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (一)80c52学习之旅-起始篇
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • .net 7 上传文件踩坑
  • .net core Swagger 过滤部分Api
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .net打印*三角形
  • .net通用权限框架B/S (三)--MODEL层(2)
  • .Net下的签名与混淆
  • :如何用SQL脚本保存存储过程返回的结果集
  • ?