同步模式之保护性暂停
-
定义
即 Guarded Suspension,用在一个线程等待另一个线程的执行结果
-
要点
- 有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject
- 如果有结果不断从一个线程到另一个线程那么可以使用消息队列(生产者/消费者)
- jdk 中,join 的实现,Future的实现,采用的就是此模式
- 因为要等待另一个的结果,因此归类到同步模式
package mythread.protectstop;
/**
* @ClassName Stop
* @Description TODO
* @Author guangmingdexin
* @Date 2020/11/8 15:47
* @Version 1.0
**/
public class ProtectedStop {
private Object response;
private final Object lock = new Object();
public Object get() {
synchronized (lock) {
while (response == null) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return response;
}
}
public void complete(Object response) {
synchronized (lock) {
this.response = response;
lock.notifyAll();
}
}
/**
* 这里如果用同步方法 则上锁的对象为 ProtectedStop的实例
* 上锁的不是同一个对象,wait 方法会报错
*
* @return
*/
public synchronized Object getResponse() {
// 同步方法
while (response == null) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return response;
}
}
ProtectedStop guardObject = new ProtectedStop();
new Thread(() -> {
// 模拟任务执行
try {
System.out.println("任务开始!");
Thread.sleep(3 * 1000);
System.out.println("任务完成,通知等待线程!");
guardObject.complete(new Object());
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "t1").start();
System.out.println("等待 ...");
Object response = guardObject.get();
System.out.println("接收到了结果!" + response.hashCode());
}
执行结果
等待 ...
任务开始!
任务完成,通知等待线程!
接收到了结果!558638686
带超时版 GuardedObject
package mythread.protectstop;
import java.util.Date;
/**
* @ClassName ProtectedStopV2
* @Description TODO
* @Author guangmingdexin
* @Date 2020/11/8 16:42
* @Version 1.0
**/
public class ProtectedStopV2 {
private Object response;
private final Object lock = new Object();
public Object get(long timeout) {
synchronized (lock) {
// 1. 记录最初时间
long begin = System.currentTimeMillis();
// 2. 记录已经经历的时间
long timePassed = 0;
while (response == null) {
// 3. 假设 millis 是 1000, 结果在 400 时唤醒了,那么还有 600 要等
long waitTime = timeout - timePassed;
System.out.println(new Date() + "还需要等待时间: " + waitTime);
if(waitTime <= 0) {
System.out.println(new Date() + "等待结束!");
break;
}
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 4. 如果被提前唤醒
timePassed = System.currentTimeMillis() - begin;
System.out.println(new Date() + "被唤醒了,过了" + timePassed);
}
return response;
}
}
public void complete(Object response) {
synchronized (lock) {
this.response = response;
lock.notifyAll();
}
}
}
ProtectedStopV2 v2 = new ProtectedStopV2();
new Thread(() -> {
try {
Thread.sleep(1000);
v2.complete(null);
Thread.sleep(1000);
v2.complete(new Object());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// Object response = v2.get(3000);
Object response = v2.get(1000);
if(response != null) {
System.out.println(new Date() + "获取到的" + response.hashCode());
}else {
System.out.println(new Date() + "获取失败!");
}
}
= null) {
System.out.println(new Date() + "获取到的" + response.hashCode());
}else {
System.out.println(new Date() + "获取失败!");
}
}