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版还介绍了一种使用管道流进行线程通信的情形,但实际上由于两个线程属于同一个进程,它们可以非常方便地共享数据,因此很少需要使用管道流进行通信,故此处不再介绍那种烦琐的方式。