闺中女儿惜春暮,愁绪满怀无释处。
前言
Condition是一个接口,它的功能与Object中的wait,notify,notifyAll类似,但是Condition更加灵活,与锁结合使用,可以等待在多个等待队列上,用来替换synchronized方法和语法以及对象的监控方法。
Conditions(也被叫做条件队列或者条件变量)提供了suspend一个线程,直到一些条件为true,被其他线程notify的方法。
由于可能多个线程同时访问某个共享状态,这个状态应该被保护,所以一些lock的形式与condition相关联。
wait
/**
* 使得当前线程等待,直到被唤醒,或者当前线程被中断。
* 与condition关联的锁是原子的释放,并且当前线程将会禁用,
* 进入休眠状态直到发生以下四种情况之一
* 1.其他线程选中当前线程被唤醒,并针对这个condition调用signal方法;
* 2.其他线程针对这个condition, 调用signalAll方法;
* 3.当前线程可中断,并且被其他线程中断了;
* 4.发生了假的唤醒
* 在上面所有的cases中,当本方法返回前,当前线程需要重新获取关联这个condition的锁。
* 当线程返回时,需要确保已经获取锁。
* 如果当前线程:
* 1.在进入此方法时,已经设置了中断状态;
* 2.如果当前线程支持中断,并且在等待的时候,被中断了;
* 那么:
* 将抛出InterruptedException,并且清除线程的中断状态。
* 对于在第一种场景中,无法确认, 那么在锁释放之前,将会检查线程的中断状态。
* 实现注意事项:
* 在调用此方法的时候,假设已经获取condition关联的锁。
* 怎么响应取决于具体的实现。通常,将会抛出异常,比如IllegalMonitorStateException,
* 并且记录原因。
* 在响应signal的时候,与一般方法相比,更加倾向于响应中断。
* 在这种情况下,如果有其他的等待线程,那么需要确保这个signal重定向到这个其他线程。
* 当前线程被中断了,将会抛出InterruptedException (当线程支持中断的时候)
*/
void await() throws InterruptedException;
/**
* 使得当前线程等待,直到被唤醒。
* 与condition关联的锁是原子的释放,并且当前线程将会禁用,
* 进入休眠状态直到发生以下三种情况之一
* 1.其他线程选中当前线程被唤醒,并针对这个condition调用signal方法;
* 2.其他线程针对这个condition, 调用signalAll方法;
* 3.发生了假的唤醒
* 在上面所有的cases中,当本方法返回前,当前线程需要重新获取关联这个condition的锁。
* 当前线程返回时,需要确保已经获取锁。
* 如果当前线程:
* 1.在进入此方法时,已经设置了中断状态;
* 2.如果在等待的时候,当前线程被中断了;
* 那么:
* 当前线程将会等待,直到被signalled。
* 最终,当前线程从本方法返回时,它的中断状态仍然是被设置的。
* 实现注意事项:
* 在调用此方法的时候,假设已经获取condition关联的锁。
* 怎么响应取决于具体的实现。通常,将会抛出异常,比如IllegalMonitorStateException,
* 并且记录原因。
*/
void awaitUninterruptibly();
/**
* 使得当前线程等待,直到被唤醒,或者当前线程被中断或者等待的时间到了。
* 与condition关联的锁是原子的释放,并且当前线程将会禁用,
* 进入休眠状态直到发生以下五种情况之一
* 1.其他线程选中当前线程被唤醒,并针对这个condition调用signal方法;
* 2.其他线程针对这个condition, 调用signalAll方法;
* 3.当前线程可中断,并且被其他线程中断了;
* 4.等待的时间到了;
* 5.发生了假的唤醒。
* 在上面所有的cases中,当本方法返回前,当前线程需要重新获取关联这个condition的锁。
* 当线程返回时,需要确保已经获取锁。
* 如果当前线程:
* 1.在进入此方法时,已经设置了中断状态;
* 2.如果当前线程支持中断,并且在等待的时候,被中断了;
* 那么:
* 将抛出InterruptedException,并且清除线程的中断状态。
* 对于在第一种场景中,无法确认, 那么在锁释放之前,应该检查线程的中断情况。
* 该方法返回的是一个还剩余的等待时间的一个估计值(单位:纳秒),当等待超时的时候,
* 返回的是一个小于等于零的值。
* 这个值可用于决定在等待返回但是返回的条件仍然不满足的场景下是否重新等待
* 或者要重新等待多长时间
* 设计建议:
* 这个方法用纳秒作为入参,可以避免在报错剩余等待时间的截断错误。
* 这种精度的损失使得programmers难以确定等待的总时间不会比指定的重新等待的系统时间短。
* 实现建议:
* 在调用此方法的时候,假设已经获取condition关联的锁。
* 怎么响应取决于具体的实现。通常,将会抛出异常,比如IllegalMonitorStateException,
* 并且记录原因。
* 在响应signal的时候,与一般方法相比,更加倾向于响应中断或者更倾向显示特定的等待时间。
* 在这两种情况下,如果有其他的等待线程,那么需要确保这个signal重定向到这个其他线程。
* 当线程被中断了,将会抛出InterruptedException (当线程支持中断的时候)
*/
//返回值:一个正值可以用作对该方法的后续调用的参数,以完成所需的等待时间;
//小于等于零表示没有可以时间可以等待。
long awaitNanos(long nanosTimeout) throws InterruptedException;
/**
* 使得当前线程等待,直到被唤醒,或者当前线程被中断或者等待的时间到了。
* 这个方法相当于waitNanos(unit.toNanos(time)) > 0
* 当前线程被中断了,将会抛出InterruptedException (当线程支持中断的时候)
*/
//如果已经过了等待的时间,那么返回false
//否则,返回true
boolean await(long time, TimeUnit unit) throws InterruptedException;
/**
* 使得当前线程等待,直到被唤醒,或者当前线程被中断或者等待的截止时间到了。
* 与condition关联的锁是原子的释放,并且当前线程将会禁用,
* 进入休眠状态直到发生以下五种情况之一
* 1.其他线程选中当前线程被唤醒,并针对这个condition调用signal方法;
* 2.其他线程针对这个condition, 调用signalAll方法;
* 3.当前线程可中断,并且被其他线程中断了;
* 4.等待的截止时间到了;
* 5.发生了假的唤醒。
* 在上面所有的cases中,当本方法返回前,当前线程需要重新获取关联这个condition的锁。
* 当线程返回时,需要确保已经获取锁。
* 如果当前线程:
* 1.在进入此方法时,已经设置了中断状态;
* 2.如果当前线程支持中断,并且在等待的时候,被中断了;
* 那么:
* 将抛出InterruptedException,并且清除线程的中断状态。
* 对于在第一种场景中,无法确认, 那么在锁释放之前,应该检查线程的中断情况。
* 该方法返回是否截止到了截止时间。
* 实现建议:
* 在调用此方法的时候,假设已经获取condition关联的锁。
* 怎么响应取决于具体的实现。通常,将会抛出异常,比如IllegalMonitorStateException,
* 并且记录原因。
* 在响应signal的时候,与一般方法相比,更加倾向于响应中断或者更倾向显示
* 是否过了特定的截止时间。
* 在这两种情况下,如果有其他的等待线程,那么需要确保这个signal重定向到这个其他线程。
* 当线程被中断了,将会抛出InterruptedException (当线程支持中断的时候)
*/
//参数deadline是一个绝对时间。
//返回值:如果过了截止时间,返回false;
//否则,发返回true。
boolean awaitUntil(Date deadline) throws InterruptedException;
ps: 注意到什么没有,awaitUninterruptibly方法是不响应中断的哦。
signal
/**
* 唤醒一个等待的线程
* 如果很多线程等待在这个condition上,那么选中一个线程唤醒。从await方法返回之前,
* 这个唤醒的线程必须重新获取了锁。
* 实现建议:
* 实现可能(通常是这样)要求当前线程在调用此方法时持有与condition关联的锁。
* 在没有持有锁的情况下,实现必须记录先决条件,以及所执行的任何操作。
* 通常,将会抛出异常,比如IllegalMonitorStateException
*/
void signal();
/**
* 唤醒所有等待的线程
* 任何等待在此condition上的线程都将会被唤醒。从await方法返回之前,
* 被唤醒的任何线程必须重新获取了锁。
* 实现建议:
* 实现可能(通常是这样)要求当前线程在调用此方法时持有与condition关联的锁。
* 在没有持有锁的情况下,实现必须记录先决条件,以及所执行的任何操作。
*通常,将会抛出异常,比如IllegalMonitorStateException
*/
void signalAll();
嘻嘻,如果文章有错误的地方,麻烦小哥哥小姐姐帮忙指出改正,一起学习,一起交流。