一 保护性暂停模式
保护性暂停模式用于接收端需要持续等待发送端发送结果完成以后才能结束的场景
例如持续等待下载结果
class GuardedObject{
private Object result;
public void put(Object result){
synchronized (this){
this.result = result;
this.notifyAll();
}
}
public Object get() throws InterruptedException {
while(result == null){
synchronized (this){
this.wait();
}
}
return result;
}
}
以上给出了保护性暂停模式的实例代码,并作出如下关键信息的解释
- 在保护性暂停模式中,接收者和发送者需要共享一个对象,使得可以实现锁共享
- 使用while(result == null)的原因是如果该锁对象执行了notifyAll方法,但是result并没有完成赋值。此时就出现了虚假唤醒的现象。因此需要加入while循环完成虚假唤醒现象的排查
二 带有超时等待的保护性暂停模式
带有虚假超时等待的保护性暂停模式主要是通过加入超时事件解决保护性暂停模式里永久等待的问题,
class GuardedObject{
private Object result;
public void put(Object result){
synchronized (this){
this.result = result;
this.notifyAll();
}
}
public Object get(long time) throws InterruptedException {
long startTime = System.currentTimeMillis();
long passedTime = 0L;
while(result == null){
if(passedTime > time){
return result;
}
synchronized (this){
this.wait(time - passedTime);
}
passedTime = System.currentTimeMillis() - startTime;
}
return result;
}
}
关键信息解释。
- 带参数的wait方法是当超时事件到达的时候,当前休眠的线程就会转到竞争锁的状态。
- 为了避免虚假唤醒的时候,超时时间被写死,需要记录一下当前虚假唤醒消耗的时间。重新设置下次休眠的时间
三 生产者消费者模式
class MessageQueue{
private LinkedList<Message> queue = new LinkedList<>();
int capcity;
public MessageQueue(int capcity) {
this.capcity = capcity;
}
public void put(Message element) throws InterruptedException {
while(queue.size() == capcity){
synchronized (this){
this.wait();
}
}
queue.addLast(element);
this.notifyAll();
}
public Message get() throws InterruptedException {
while ((queue.size() == 0)) {
synchronized (this){
this.wait();
}
}
Message t = queue.removeFirst();
this.notifyAll();
return t;
}
}
class Message{
private int id;
Object value;
public Message(int id, Object value) {
this.id = id;
this.value = value;
}
}