多執行緒設計模式之保護性暫停模式
定義
保護性暫停模式(Guarded Suspension Design Pattern):當執行緒在訪問某個物件時,發現條件不滿足時,就暫時掛起等待條件滿足時再次訪問,
如果某個結果需要在多執行緒之間傳遞,則可以讓這些執行緒關聯到一個物件GuardedObject,但是如果這個結果需要不斷的從一個執行緒到另一個執行緒那么可以使用訊息佇列(生產者/消費者)
Thread.join()、Future就采用了保護性暫停模式,
簡單實作
package com.morris.concurrent.pattern.guardedsuspension.v2;
public class GuardedObject<V> {
private final Object lock = new Object();
private V v;
private boolean isFinished;
public void set(V v) {
synchronized (lock) {
this.v = v;
isFinished = true;
lock.notifyAll();
}
}
public V get() throws InterruptedException {
synchronized (lock) {
while (!isFinished) {
lock.wait();
}
}
return v;
}
}
超時實作
public V get(long millis) {
synchronized (lock) {
while (!isFinished) {
try {
lock.wait(millis);
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return v;
}
上面的超時實作有點小問題,
分析:假如超時時間是5s,但是在第2s的時候別人把這個執行緒中斷了但是此時還沒有結果,那么這個執行緒就會進入下次回圈繼續等待5s,這樣這個執行緒就等待7s了,
最終實作如下:
public V get(long millis) {
long begin = System.currentTimeMillis(); // 等待開始時間
long waitedTime = 0; // 等待了多長時間
synchronized (lock) {
while (!isFinished) {
if(waitedTime >= millis) {
System.out.println("超時了,不等了");
break;
}
try {
lock.wait(millis - waitedTime); // 繼續等待剩余時間
break;
} catch (InterruptedException e) {
waitedTime = System.currentTimeMillis() - begin;
System.out.println("被中斷了,等了" + waitedTime + "ms");
}
}
}
return v;
}
使用保護性暫停模式實作Future和Callable
public interface Callable<T> {
T call();
}
public interface Future<T> {
T get();
}
public class FutureTask<T> implements Future<T> {
private boolean isFinish;
private T t;
public synchronized void set(T t) {
this.t = t;
this.isFinish = true;
this.notifyAll();
}
@Override
public synchronized T get() {
while (!isFinish) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return t;
}
}
public abstract class Executors {
public static <T> Future<T> newSingleThreadPool(Callable<T> callable) {
FutureTask<T> future = new FutureTask<>();
new Thread(()->{
T t = callable.call();
future.set(t);
}).start();
return future;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/57542.html
標籤:其他
上一篇:【干貨干貨!內附原始碼】多邊形的面積及周長計算~java Swing開發可視化小程式,exe4j打包成exe可執行檔案
