16.6.2 使用Condition控制线程通信
16.6.2 使用Condition控制线程通信
synchronized同步的 使用同步监视器进行通信
如果程序不使用synchronized
关键字来保证同步,而是直接使用Lock
对象来保证同步,则系统中不存在隐式的同步监视器,也就不能使用wait()
、notify()
、notifyAll()
方法进行线程通信了。
Lock对象同步的使用Condition对象通信
当使用Lock
对象来保证同步时,Java
提供了一个Condition
类来保持协调,使用Condition
可以让那些已经得到Lock
对象却无法继续执行的线程释放Lock
对象,Condition
对象也可以唤醒其他处于等待的线程
Condition
将同步监视器方法(wait()
、notify()
和notifyAll()
)分解成截然不同的对象,以便通过将这些对象与Lock
对象组合使用,为每个对象提供多个等待集(wait-set
)。
在这种情况下,
Lock
替代了同步方法或同步代码块,Condition
替代了同步监视器的功能
如何创建Condition
实例
Condition
实例被绑定在一个Lock
对象上。要获得特定Lock
实例的Condition
实例,调用Lock
对象的newCondition
方法即可。
Condition
类提供了如下三个方法。
方法 | 描述 |
---|---|
void await() |
类似于隐式同步监视器上的wait() 方法,导致当前线程等待,直到其他线程调用该Condition 的signal() 方法或signalAll() 方法来唤醒该线程 |
void signal() |
唤醒在此Lock 对象上等待的单个线程。如果所有线程都在该Lock 对象上等待,则会选择唤醒其中一个线程。选择是仼意性的。只有当前线程放弃对该Lock 对象的锁定后(使用await 方法),才可以执行被唤醒的线程。 |
void signalAll() |
唤醒在此Lock 对象上等待的所有线程。只有当前线程放弃对该Lock 对象的锁定后才可以执行被唤醒的线程。 |
await方法变体 | 描述 |
---|---|
boolean await(long time, TimeUnit unit) |
Causes the current thread to wait until it is signalled or interrupted, or the specified waiting time elapses. |
long awaitNanos(long nanosTimeout) |
Causes the current thread to wait until it is signalled or interrupted, or the specified waiting time elapses. |
void awaitUninterruptibly() |
Causes the current thread to wait until it is signalled. |
boolean awaitUntil(Date deadline) |
Causes the current thread to wait until it is signalled or interrupted, or the specified deadline elapses. |
程序 使用Lock同步 使用Condition通信
账户类
下面程序中Account
使用Lock
对象来控制同步,并使用Condition
对象来控制线程的协调运行
1 |
|
用该程序与上一节的Account.java
进行对比,不难发现这两个程序的逻辑基本相似,只是现在显式地使用Lock
对象来充当同步监视器,然后需要使用Condition
对象来暂停、唤醒指定线程。
该示例程序的其他类与前一个示例程序的其他类完全一样,该程序的运行效果与前一个示例程序的运行效果完全一样.
使用管道流进行线程通信
本书第1版还介绍了一种使用管道流进行线程通信的情形,但实际上由于两个线程属于同一个进程,它们可以非常方便地共享数据,因此很少需要使用管道流进行通信,故此处不再介绍那种烦琐的方式。