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

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

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

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

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();

    }

}

执行结果:

?


1

2

3

4

5

6

7

8

9

10

11

12

[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对象只有在更加困难的多线程问题中才是必需的

时间: 2024-10-11 03:21:35

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

Java并发编程实现概览

1.同步 如何同步多个线程对共享资源的访问是多线程编程中最基本的问题之一. 当多个线程并发访问共享数据时会出现数据处于计算中间状态或者不一致的问题,从而影响到程序的正确运行.我们通常把这种情况叫做竞争条件(race condition),把并发访问共享数据的代码叫做关键区域(critical section). 同步就是使得多个线程顺序进入关键区域从而避免竞争条件的发生. 2.线程安全性 编写线程安全的代码的核心是要对状态访问操作进行管理,尤其是对共享的和可变的状态访问.  线程安全性的定义:当

oracle显式授权和隐式授权

oracle对象的授权 Oracle授权 一.授权语法 GRANT语法: 1.显式授权(直接将对象授权给用户) GRANT privilege [, ...] ON object [, ...]  TO  { Public| Group | Username|role} [WITH GRANT OPTION ] 例子grant read,write on directory dir_home to public 2.隐式授权(通过将角色授权给用户) GRANT role TO  { Public

《Java并发编程从入门到精通》显示锁Lock和ReentrantLock

作者:张振华    购买链接:天猫商城  JD商城  当当书店   显示锁Lock和ReentrantLock Lock是一个接口提供了无条件的.可轮询的.定时的.可中断的锁获取操作,所有加锁和解锁的方法都是显式的.包路径是:java.util.concurrent.locks.Lock.核心方法是lock(),unlock(),tryLock(),实现类有ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock

Java并发开发:Lock框架详解

摘要: 我们已经知道,synchronized 是java的关键字,是Java的内置特性,在JVM层面实现了对临界资源的同步互斥访问,但 synchronized 粒度有些大,在处理实际问题时存在诸多局限性,比如响应中断等.Lock 提供了比 synchronized更广泛的锁操作,它能以更优雅的方式处理线程同步问题.本文以synchronized与Lock的对比为切入点,对Java中的Lock框架的枝干部分进行了详细介绍,最后给出了锁的一些相关概念. 一. synchronized 的局限性

Java并发编程示例(三):线程中断_java

一个多线程的Java程序,直到所有线程执行完成,整个程序才会退出.(需要注意的是,是所有非后台线程(non-daemon thread)执行完成:如果一个线程执行了System.exit()方法,程序也会退出.)有时,你想中止一个线程的执行,例如你想退出程序,或者你想取消一个正在执行的任务等. Java提供了中断机制,可以让我们显式地中断我们想中止执行的线程.中断机制的一个特征就是我们可以检查线程是否已经被中断,进而决定是否响应中止请求.线程也可以忽略中止请求,继续执行. 在本节,我们所开发的示

JAVA并发(三)

并发 Table of Contents 1 什么是并发问题. 2 java中synchronized的用法 3 Java中的锁与排队上厕所. 4 何时释放锁? 5 Lock的使用 6 利用管道进行线程间通信 7 阻塞队列 8 使用Executors.Executor.ExecutorService.ThreadPoolExecutor 9 并发流程控制 10 并发3定律 11 由并发到并行 1 什么是并发问题. 多个进程或线程同时(或着说在同一段时间内)访问同一资源会产生并发问题. 银行两操作

EntityFramework Core并发导致显式插入主键问题

前言 之前讨论过EntityFramework Core中并发问题,按照官网所给并发冲突解决方案以为没有什么问题,但是在做单元测试时发现too young,too simple,下面我们一起来看看. .NET Core 1.1单元测试问题 我们循序渐进,首先从单元测试开始说起,可能其中就有你在.NET Core上进行单元测试会遇到的问题,别着急,不妨一看.我们需要创建.NET Core类库,,如下: 接下来对project.json进行如下修改. { "version": "

Java 并发/多线程教程(三)-多线程的开销

        本系列译自jakob jenkov的Java并发多线程教程,个人觉得很有收获.由于个人水平有限,不对之处还望矫正!     应用程序由单线程到多线程,不仅仅给我带来了便利,同时也也带来了一些开销.不要因为你会多线程,就把所有的程序都设计成多线程.如果把单线程改成多线程,你获得到的好处要远远超过开销,对于这一点你应该有个清醒的认识.当你犹豫是应该用多线程还是单线程时,你要衡量性能和响应时间,而不是靠猜测. 更复杂的设计 尽管多线程应用程序的某些部分比单线程应用程序更简单,但其他部分

Java 并发工具包 java.util.concurrent 用户指南

译序 本指南根据 Jakob Jenkov 最新博客翻译,请随时关注博客更新:http://tutorials.jenkov.com/java-util-concurrent/index.html. 本指南已做成中英文对照阅读版的 pdf 文档,有兴趣的朋友可以去 Java并发工具包java.util.concurrent用户指南中英文对照阅读版.pdf[带书签] 进行下载. 1. java.util.concurrent - Java 并发工具包 Java 5 添加了一个新的包到 Java 平