多线程同步设计模式之保护性暂停
- 用于一个线程(T1)等待另一个线程(T2)执行的结果(结果单一,若结果需要源源不断的从一个线程传递到另一个线程,使用消息队列)
- 将T1和T2线程关联到同一个GuardedObject(内含response属性)对象上
- T1线程等待response的值
- T2线程执行并为response赋值,随后通知T1线程
- JDK中的join和Future均采用此模式
@Slf4j(topic = "c.Test201")
public class Test201 {
public static void main(String[] args) {
GuardedObject guardedObject = new GuardedObject();
new Thread(()->{
log.debug("等待结果");
List<String> download = (List<String>) guardedObject.get(1);
log.debug("结果的大小是:{}",download.size());
},"t1").start();
new Thread(()->{
log.debug("执行下载");
try {
List<String> download = Downloader.download();
guardedObject.complete(download);
} catch (IOException e) {
e.printStackTrace();
}
},"t2").start();
}
}
class GuardedObject {
private Object response;
public Object get(long timeout) {
synchronized (this) {
long begin = System.currentTimeMillis();
long passedTime = 0;
while (response == null) {
if (passedTime >= timeout) {
break;
}
try {
this.wait(timeout-passedTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
passedTime = System.currentTimeMillis() - begin;
}
return response;
}
}
public void complete(Object response) {
synchronized (this) {
this.response = response;
this.notifyAll();
}
}
}
public class Downloader {
public static List<String> download() throws IOException {
HttpURLConnection conn = (HttpURLConnection) new URL("https://www.baidu.com/").openConnection();
List<String> lines = new ArrayList<>();
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
}
return lines;
}
}