通過使用ComputedMap的Future,可以安排「僅一次」執行背景計算。未來代表了計算價值的任務。未來由ComputedMap創建,同時傳遞給ExecutorService進行後臺執行。執行器可以配置您自己的ThreadFactory實現,創建低優先級的線程,例如
class LowPriorityThreadFactory implements ThreadFactory
{
public Thread newThread(Runnable r) {
Tread t = new Thread(r);
t.setPriority(MIN_PRIORITY);
return t;
}
}
當需要的價值,你的高優先級的線程,然後從地圖上獲取的未來,並調用get()方法來檢索結果,等待它可以根據需要計算。爲了避免priority inversion你添加一些額外的代碼到任務:
class HandlePriorityInversionTask extends FutureTask<ResultType>
{
Integer priority; // non null if set
Integer originalPriority;
Thread thread;
public ResultType get() {
if (!isDone())
setPriority(Thread.currentThread().getPriority());
return super.get();
}
public void run() {
synchronized (this) {
thread = Thread.currentThread();
originalPriority = thread.getPriority();
if (priority!=null) setPriority(priority);
}
super.run();
}
protected synchronized void done() {
if (originalPriority!=null) setPriority(originalPriority);
thread = null;
}
void synchronized setPriority(int priority) {
this.priority = Integer.valueOf(priority);
if (thread!=null)
thread.setPriority(priority);
}
}
這需要提高任務的優先級的線程調用get()
如果任務沒有完成的優先照顧,並優先返回任務完成時爲原始,通常或以其他方式。 (爲了保持簡短,代碼並不檢查優先級是否確實較高,但很容易添加。)
當高優先級任務調用get()時,未來可能尚未開始執行。您可能會試圖通過設置執行程序服務使用的線程數量的上限來避免這種情況,但這可能是一個壞主意,因爲每個線程都可能以高優先級運行,因此可能會消耗盡可能多的cpu OS將其切換出來。池應該與硬件線程的數量相同,例如,將池的大小設爲Runtime.availableProcessors()
。如果任務沒有開始執行,而不是等待執行程序安排它(這是一種優先級反轉形式,因爲高優先級線程正在等待低優先級線程完成),那麼您可以選擇取消它當前的執行程序並重新提交執行程序只運行高優先級的線程。
您想預先計算並緩存預計算緩存的密鑰?你可以,呃...將它存儲在預計算緩存中? – 2010-07-13 18:21:22
@BlueRaja,符合要求#1,但不符合#2,#3或#4。 – finnw 2010-07-16 15:38:03