文档章节

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

摆渡者
 摆渡者
发布于 2015/10/12 09:39
字数 720
阅读 325
收藏 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对象只有在更加困难的多线程问题中才是必需的


© 著作权归作者所有

共有 人打赏支持
摆渡者
粉丝 330
博文 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并发编程之wait¬ify VS lock&condition

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

若鱼1919
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
Java线程:条件变量 lock

条件变量是Java5线程中很重要的一个概念,顾名思义,条件变量就是表示条件的一种变量。但是必须说明,这里的条件是没有实际含义的,仅仅是个标记而已,并且条件的含义往往通过代码来赋予其含...

古月楼
2013/08/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

emoji

前言:随着iOS系统版本的升级,对原生emoji表情的支持也越来越丰富。emoji表情是unicode码中为表情符号设计的一组编码,当然,还有独立于unicode的另一套编码SBUnicode,在OS系统中,这两种编...

HeroHY
28分钟前
1
0
rabbitmq学习(二)

生产者消费者初级案列 ChannelUtils package com.hensemlee.rabbitmq;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.Connecti......

hensemlee
38分钟前
1
0
MarkDown入门简介

Markdown是一种可以使用普通文本编辑器编写的标记语言,通过类似HTML的标记语法,它可以使普通文本内容具有一定的格式。Markdown的语法简洁明了、学习容易,而且功能比纯文本更强,因此有很多...

一零贰IV
41分钟前
1
0
druid配置db2参考记录

Driver Name:COM.ibm.db2.jdbc.app.DB2 Driver Type 4 Driver URL Pattern:jdbc:db2://ServerIP:50000/databasename ${driverClassName} 这个参数没有在spring相关的properties文件中配置 ......

tonyfox
45分钟前
1
0
用户体验要素——以用户为设计中心

一、用户体验是什么 产品会与外界发生联系,人们如何去使用产品,人们使用产品无非解决两种问题,一,提高效率;二娱乐。而用户体验兼顾着功能和界面两个方面,为的是“提高人们的工作效率”...

铸剑为犁413
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部