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

目录
相关文章
|
1月前
|
安全 Java 编译器
Java对象一定分配在堆上吗?
本文探讨了Java对象的内存分配问题,重点介绍了JVM的逃逸分析技术及其优化策略。逃逸分析能判断对象是否会在作用域外被访问,从而决定对象是否需要分配到堆上。文章详细讲解了栈上分配、标量替换和同步消除三种优化策略,并通过示例代码说明了这些技术的应用场景。
Java对象一定分配在堆上吗?
|
1月前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
2月前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
54 17
|
1月前
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
|
1月前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
47 4
|
1月前
|
Java 数据库连接 数据库
如何构建高效稳定的Java数据库连接池,涵盖连接池配置、并发控制和异常处理等方面
本文介绍了如何构建高效稳定的Java数据库连接池,涵盖连接池配置、并发控制和异常处理等方面。通过合理配置初始连接数、最大连接数和空闲连接超时时间,确保系统性能和稳定性。文章还探讨了同步阻塞、异步回调和信号量等并发控制策略,并提供了异常处理的最佳实践。最后,给出了一个简单的连接池示例代码,并推荐使用成熟的连接池框架(如HikariCP、C3P0)以简化开发。
56 2
|
1月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
2月前
|
存储 Java 数据管理
Java零基础-Java对象详解
【10月更文挑战第7天】Java零基础教学篇,手把手实践教学!
37 6
|
1月前
|
存储 缓存 NoSQL
一篇搞懂!Java对象序列化与反序列化的底层逻辑
本文介绍了Java中的序列化与反序列化,包括基本概念、应用场景、实现方式及注意事项。序列化是将对象转换为字节流,便于存储和传输;反序列化则是将字节流还原为对象。文中详细讲解了实现序列化的步骤,以及常见的反序列化失败原因和最佳实践。通过实例和代码示例,帮助读者更好地理解和应用这一重要技术。
48 0
|
2月前
|
存储 前端开发 Java
你还没有对象吗?java带你创建一个吧
你还没有对象吗?java带你创建一个吧
25 0