文档章节

Java并发(三)使用显式的Lock和Condition对象

摆渡者
 摆渡者
发布于 2015/10/12 09:39
字数 720
阅读 342
收藏 3

    在之前的Java并发(一)wait()与notifyAll()一文中的例子中,我们使用了wait()和notifyAll()来模拟了给汽车打蜡和抛光的情景。在JavaSE5中,还提供了java.util.concurrent.locks.Condition对象供我们使用。你可以在Condition上调用await()来挂起一个任务。当外部条件发生变化,意味着某个任务应该继续执行时,你可以通过调用signal()来通知这个任务,或者调用signalAll()来唤醒所有在这个Condition上被其自身挂起的任务(与使用signal()相比,signalAll()是更安全的方式)。

    下面是WaxOnMatic.java的重写版本,它包含了一个Condition,用来在waitForWaxing()或waitForBuffing()内部挂起一个任务:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Car {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    private boolean waxOn = false;//是否上蜡
    //上蜡
    public void waxed() {
        lock.lock();
        try {
            waxOn = true;
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }
    //抛光
    public void buffed() {
        lock.lock();
        try {
            waxOn = false;
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }
    //等待上蜡
    public void waitForWaxing() throws InterruptedException {
        lock.lock();
        try {
            while(waxOn == false) {
                condition.await();
            }
        } finally {
            lock.unlock();
        }
    }
    //等待抛光
    public void waitForBuffing() throws InterruptedException {
        lock.lock();
        try {
            while(waxOn == true) {
                condition.await();
            }
        } finally {
            lock.unlock();
        }
        
    }
}


class WaxOnTask implements Runnable {
    private Car car;
    private String name;
    public WaxOnTask(String name, Car car) {
        this.name = name;
        this.car = car;
    }
    @Override
    public void run() {
        try {
            while(!Thread.interrupted()) {
                System.out.println("[" + name + "] is Wax on!");//正在上蜡
                TimeUnit.MILLISECONDS.sleep(300);
                car.waxed();//上蜡完成
                car.waitForBuffing();//等待抛光
            }
        } catch (InterruptedException e) {
            System.out.println("[" + name + "] Exiting WaxOnTask via interrupt.");
        }
    }
}
class BuffTask implements Runnable {
    private Car car;
    private String name;
    public BuffTask(String name, Car car) {
        this.name = name;
        this.car = car;
    }
    @Override
    public void run() {
        try {
            while(!Thread.interrupted()) {
                car.waitForWaxing();//等待上蜡
                System.out.println("[" + name + "] Buffing...");//正在抛光
                TimeUnit.MILLISECONDS.sleep(300);
                car.buffed();//抛光完成
            }
        } catch (InterruptedException e) {
            System.out.println("[" + name + "] Exiting BuffTask via interrupt.");
        }
    }
}

public class WaxOMatic2 {
    public static void main(String[] args) throws Exception {
        Car car = new Car();
        ExecutorService exec = Executors.newCachedThreadPool();
        //上蜡
        exec.execute(new WaxOnTask("Waxx", car));
        //抛光
        exec.execute(new BuffTask("Buff", car));
        //运行一段时间,停止ExecutorService
        TimeUnit.SECONDS.sleep(3);
        exec.shutdownNow();
    }
}

执行结果:

[Waxx] is Wax on!
[Buff] Buffing...
[Waxx] is Wax on!
[Buff] Buffing...
[Waxx] is Wax on!
[Buff] Buffing...
[Waxx] is Wax on!
[Buff] Buffing...
[Waxx] is Wax on!
[Buff] Buffing...
[Buff] Exiting BuffTask via interrupt.
[Waxx] Exiting WaxOnTask via interrupt.

    从代码中可以看到,Car的构造器中,单个的Lock将产生一个Condition对象,这个对象被用来管理任务之间的通信。但是,这个Condition对象不包含任何有关处理状态的信息,因此你需要管理额外的表示处理状态的信息,即boolean waxOn。

    注意:每个lock()的调用都必须紧跟一个try-finally子句,用来保证在所有情况下都可以释放锁。在使用内建版本时,任务在可以调用await(),signal()或signalAll()之前,必须拥有这个锁。

    另外还需要注意的是,这个解决方案比之前一个更加复杂,在本例中这种复杂性并未使你收获更多。Lock和Condition对象只有在更加困难的多线程问题中才是必需的


© 著作权归作者所有

共有 人打赏支持
摆渡者
粉丝 336
博文 171
码字总数 205876
作品 0
浦东
程序员
私信 提问
JAVA线程13 - 新特性:Lock和条件变量

一、Lock 1. 概述 Lock是JDK 1.5以后将同步和锁封装成了对象。Lock是对之前synchronized的替代。 Lock接口的实现类:互斥锁ReentrantLock 。 2. synchronized与Lock区别 synchronized对于锁的...

小米米儿小
2014/03/05
0
0
显式锁(java.util.Concurrent)

一、前言   在分析完了集合框架后,很有必要接着分析java并发包下面的源码,JUC(java.util.concurrent)源码也是我们学习Java迈进一步的重要过程。我们分为几个模块进行分析,首先是对锁模...

狼王黄师傅
2018/11/27
0
0
java并发编程之wait¬ify VS lock&condition

jdk5之前线程同步可以用synchronized/wait/notify来进行控制,jdk5以后新添加了lock/condition。他们之间有什么联系与区别的?本文就用一个例子循序渐进的给大家展示一下: 首先来看一个有界...

若鱼1919
2018/07/06
0
0
读书笔记之《Java并发编程的艺术》-java中的锁

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
0
Java并发编程利用 Condition 实现阻塞队列

什么是阻塞队列 BlockingQueue 队列是一种数据结构,它的特点是先进先出(First In First Out),它有两个基本操作:在队列尾部加入一个元素,从队列头部移除一个元素。队列在多线程应用中,...

行走在旅途中
2017/11/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

通俗易懂解释网络工程中的技术,如STP,HSRP等

导读 在面试时,比如被问到HSRP的主备切换时间时多久,STP几个状态的停留时间,自己知道有这些东西,但在工作中不会经常用到,就老是记不住,觉得可能还是自己基础不够牢固,知识掌握不够全面...

问题终结者
28分钟前
3
0
看了一下Maven的内容

了解了Maven其实是一个跨IDE的标准构建工具,能推广的原因估计是借了仓库的便利。 另一个作用是可以通过Maven的功能在社区版的IDEA去创建Web项目,下次实践看看

max佩恩
32分钟前
1
0
day27:expect批量杀进程|

1、linux下当前目录有一个文件ip-pwd.ini,内容如下: [root@localhost_002 shell100]# cat ip-pwd.ini 10.111.11.1,root,xyxyxy10.111.11.2,root,xzxzxz10.111.11.3,root,12345610.......

芬野de博客
今天
3
0
分布式之数据库和缓存双写一致性方案解析(二)

引言 该文是对《分布式之数据库和缓存双写一致性方案解析》,一文的补充。博主在该文中,提到了这么一句话 应该没人问我,为什么没有先更新缓存,再更新数据库这种策略。 博主当时觉得,这种...

hensemlee
今天
4
0
druid安装与案例

druid 可以运行在单机环境下,也可以运行在集群环境下。简单起见,我们先从单机环境着手学习。 环境要求 java7 或者更高版本 linux, macOS或者其他unix系统(不支持windows系统) 8G内存 2核C...

hblt-j
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部