Condition介绍
Condition接口也提供了类似Object的监视器方法,与Lock配合可以实现等待/通知模式,但是这两者在使用方式以及功能特性上还是有差别的。Object上的监视器只有一个等待队列,但是Condition上可以有多个等待队列
Condition是对象监视器的替代品,拓展了监视器的语义
Condition的实现,主要包括:等待队列、等待和通知
等待队列
等待队列是一个FIFO的队列,在队列中的每个节点都包含了一个线程引用,该线程就是在Condition对象上等待的线程,如果一个线程调用了Condition.await()方法,那么该线程将会释放锁、构造成节点加入等待队列并进入等待状态.
等待
调用Condition的await()方法(或者以await开头的方法),会使当前线程进入等待队列并释放锁,同时线程状态变为等待状态。当从await()方法返回时,当前线程一定获取了Condition相关联的锁。
通知
调用Condition的signal()方法,将会唤醒在等待队列中等待时间最长的节点(首节点),在唤醒节点之前,会将节点移到同步队列中。
实列1:(不唤醒)
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyConditionTest {
private static Lock lock=new ReentrantLock();
private static Condition condition=lock.newCondition();
public static void main(String[] arg) throws InterruptedException
{
new Thread(()->
{
try {
ConditionWait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// new Thread(()->{ConditionSignal();}).start();
Thread.sleep(1000);
}
public static void ConditionWait() throws InterruptedException
{
lock.lock();
try{
//当前线程从运行状态进入等待状态或者中断,直到被通知唤醒。
System.out.println("start await");
condition.await();
System.out.println("end await");
}finally {
lock.unlock();
}
}
public static void ConditionSignal()
{
lock.lock();
try
{
//唤醒一个等待线程
System.out.println("signal");
condition.signal();
}finally {
lock.unlock();
}
}
}
结果:start await
实列2:(唤醒)
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyConditionTest {
private static Lock lock=new ReentrantLock();
private static Condition condition=lock.newCondition();
public static void main(String[] arg) throws InterruptedException
{
new Thread(()->
{
try {
ConditionWait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{ConditionSignal();}).start();
Thread.sleep(1000);
}
public static void ConditionWait() throws InterruptedException
{
lock.lock();
try{
//当前线程从运行状态进入等待状态或者中断,直到被通知唤醒。
System.out.println("start await");
condition.await();
System.out.println("end await");
}finally {
lock.unlock();
}
}
public static void ConditionSignal()
{
lock.lock();
try
{
//唤醒一个等待线程
System.out.println("signal");
condition.signal();
}finally {
lock.unlock();
}
}
}
结果:
start await
signal
end await
Condition类的方法
方法 | 说明 |
public void await() |
当前线程从运行状态进入等待状态或者中断,直到被通知唤醒。 |
public boolean await(long time, TimeUnit unit) |
当前线程进入等待状态,直到被通知、中断或者超时 |
public long awaitNanos(long nanosTimeout) |
使当前线程等待直到发出信号。 |
public long awaitUninterruptibly() |
当前线程进入等待状态直到被通知,从方法名称上可以看出该方法对中断不敏感 |
public long awaitUntil() |
当前线程进入等待状态直到被通知、中断或者到某个时间。如果没有到指定时间就被通知,方法返回true,否则,表示到了指定时间,返回false |
public void signal() |
唤醒一个等待线程 |
public void signalAll() |
唤醒所有等待线程。 |
Object 的监视器方法与 Condition 接口的对比
对比项 | Object Monitor Methods | Condition |
前置条件 | 获取对象的锁 | 调用Lock.lock()获取锁 调用Lock.newCondition()获取Condition对象 |
调用方式 | 直接调用,如:Object.wait() | 直接调用,如:condition.await() |
等待队列个数 | 一个 | 多个 |
当前线程释放锁并进入等待状态 | 支持 | 支持 |
当前线程释放锁并进入等待状态, 在等待状态中不响应中断 |
不支持 | 支持 |
当前线程释放锁并进入等待超时状态 | 支持 | 支持 |
当前现场释放锁并进入等待状态到将来某个时间 | 不支持 | 支持 |
唤醒等待队列中的一个线程 | 支持 | 支持 |
唤醒等待队列中的所有线程 | 支持 | 支持 |