我有一個包含'資源管理器'類的多線程Java應用程序。有條件的任務調度 - 多線程Java應用程序
該類提供了可能作爲初始化參數請求的資源列表。然後它檢查每個文件的本地文件系統並將確定爲本地的文件添加到列表中。
當類收到以下的資源請求之一發生:
如果資源被確定爲本地(列表):提供URI,其中可以發現。
如果資源是遠程的(不在列表中):安排工作人員獲取資源。任務完成時,工作人員將通知經理,並且本地資源列表將被更新。 (請求線程不會等待 - 無論是否存在)。
由於多個線程可以請求資源,ReadWriteLock用於協調列表訪問。許多線程可以同時讀取列表,並且當需要更新時,將使用writeLock。
問題在於爲任何特定的遠程資源調度後臺工作。如果多個線程安排資源相同資源的工作人員,則需要不必要的開銷(即使重複任務因爲檢查此情況而未完全執行)。爲了達到最高的效率可能我想了解一下下面的實現:
private final ReadWriteLock lock = new ReentrantReadWriteLock();
//assume each resource object has a volatile boolean "scheduled"
//with isScheduled() and setSheduled() setter/getter;
//assume the resource list is thread safe
public URI requestResource(Resource theResource){
URI resourceId = null;
//many threads can enter here
lock.readLock().lock();
try{
//if our resource is not in the list
if(!localResouces.contains(theResource)){
//double-check idiom...does it work here?
//if the resource isn't scheduled
if(!theResource.isScheduled()){
//only one thread may enter here
synchronized(this){
if(!theResource.isScheduled()){
//schedule task here...
theResource.setScheduled(true);
}
}
}
} else {
//its local, return the location
resouceId = theResource.getURI();
}
} finally {
lock.readLock().unlock();
}
//requesting object will deal with null value;
return resouceId;
}
和當工人完成:
public void update(Resource theResource){
//ensures no threads in the read block
lock.writeLock().lock();
try {
//update the list (would check result IRL, and not add if problem found)
localResources.add(theResource);
//set the scheduled field
theResource.setScheduled(false);
} finally {
lock.writeLock().unlock();
}
}
同樣,我想最大限度地提高效率。我找不到與這種情況相匹配的示例 - 即允許對常用操作進行高吞吐量,同時允許以最小的阻塞/開銷對任務進行調度。
這種方法有什麼問題?第一種方法必須同時獲得讀取鎖定和同步,但是update方法只需要獲取寫入鎖定,因爲isScheduled檢查被封裝在讀取塊中。這是否提供線程安全調度和數據訪問?
編輯:
伊夫測試如上所述的方法和我看到正確的行爲。我仍然不確定這是否真的是「線程安全的」。
你爲什麼需要本地資源列表?爲什麼不在'Resource'中有一個標誌來表示它是本地的? – irreputable 2013-02-18 22:05:23
我的目標是儘可能減少同步塊的入口。你能否詳細說明這個建議如何幫助實現這一目標? – 2013-02-18 22:35:51