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

目录
相关文章
|
6月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
881 157
|
6月前
|
Java 大数据 Go
从混沌到秩序:Java共享内存模型如何通过显式约束驯服并发?
并发编程旨在混乱中建立秩序。本文对比Java共享内存模型与Golang消息传递模型,剖析显式同步与隐式因果的哲学差异,揭示happens-before等机制如何保障内存可见性与数据一致性,展现两大范式的深层分野。(238字)
187 4
|
9月前
|
Java API 调度
从阻塞到畅通:Java虚拟线程开启并发新纪元
从阻塞到畅通:Java虚拟线程开启并发新纪元
467 83
|
6月前
|
缓存 安全 Java
如何理解Java中的并发?
Java并发指多任务交替执行,提升资源利用率与响应速度。通过线程实现,涉及线程安全、可见性、原子性等问题,需用synchronized、volatile、线程池及并发工具类解决,是高并发系统开发的关键基础。(238字)
363 5
|
9月前
|
存储 Java 调度
Java虚拟线程:轻量级并发的革命性突破
Java虚拟线程:轻量级并发的革命性突破
493 83
|
8月前
|
缓存 安全 Java
Java反射机制:动态操作类与对象
Java反射机制是运行时动态操作类与对象的强大工具,支持获取类信息、动态创建实例、调用方法、访问字段等。它在框架开发、依赖注入、动态代理等方面有广泛应用,但也存在性能开销和安全风险。本文详解反射核心API、实战案例及性能优化策略,助你掌握Java动态编程精髓。
|
9月前
|
SQL 缓存 安全
深度理解 Java 内存模型:从并发基石到实践应用
本文深入解析 Java 内存模型(JMM),涵盖其在并发编程中的核心作用与实践应用。内容包括 JMM 解决的可见性、原子性和有序性问题,线程与内存的交互机制,volatile、synchronized 和 happens-before 等关键机制的使用,以及在单例模式、线程通信等场景中的实战案例。同时,还介绍了常见并发 Bug 的排查与解决方案,帮助开发者写出高效、线程安全的 Java 程序。
493 0
|
8月前
|
存储 人工智能 JavaScript
Java从作用域到对象高级应用​
本内容详细讲解了JavaScript中的作用域类型(函数作用域、块作用域、全局作用域)、作用域链、垃圾回收机制、闭包、变量提升、函数参数、数组方法、内置构造函数、对象高级知识、原型链、对象赋值、深浅拷贝、递归、异常处理及this指向等内容,全面覆盖JS核心概念与编程技巧。
99 0
|
9月前
|
存储 Java
Java对象的内存布局
在HotSpot虚拟机中,Java对象的内存布局分为三部分:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。对象头包含Mark Word、Class对象指针及数组长度;实例数据存储对象的实际字段内容;对齐填充用于确保对象大小为8字节的整数倍。
182 0