[英]Simple LinkedList and Queue synchronization
對於大學作業,我需要實施醫院病人等待系統的一部分。系統使用等待名單上的患者集合,以及在特定時期(例如今年)注冊操作的一組患者。
我使用HashSet和LinkedList實現了如下所需的方法。 該方法幾乎完全同步,所以我想知道是否有更低效的實現同步更少,或者使用鎖更精細的讀寫同步?
public Class OperationPeriod {
...
private Set<Patient> registeredPatients=new HashSet<Patient>();
private Collection<Patient> waitingListPatients=new LinkedList<Patient>();
private int capacity;
...
public boolean bookOperation(Patient patient){
if (!Operation.checkHasMetRequirements(patient)) {
return false;
}
//patient could already be registered
synchronized(this) {
if(registeredPatients.contains(patient)) {
return true;
}
if(waitingListPatients.contains(patient) ) {
return false;
}
//Not already registered so register or add to waiting list
return addPatient(patient);
}
}
private boolean addPatient(Patient patient) {
if(registeredPatients.size() < capacity) {
registeredPatients.add(patient);
return true;
}
else {
waitingListPatients.add(patient);
return false;
}
}
你這里只有一些代碼,但你的同步看起來不錯。
僅供參考,您的LinkedList.contains
需要O(n)
。 我會做以下其中一項
使用具有常量查找但仍保持順序的LinkedHashSet
。 但是,根據您以后的使用情況,這可能不會令人滿意。
使用HashSet
來擴充LinkedList
。 除了檢查.contains()
時,請使用LinkedList
。
您可以考慮讀/寫鎖...但選擇這取決於您對用戶閱讀集合的頻率以及閱讀和寫作的期望。
A.用戶嘗試添加已存在的患者的次數(閱讀)
B.您經常閱讀上面未顯示的應用程序其他部分的列表(閱讀)
C.用戶成功添加患者的次數(讀取+寫入)
如果與C相比(A + B)很大,請考慮像java.util.concurrent.locks.ReentrantReadWriteLock
這樣的讀/寫鎖。 調用readLock()開始讀取(只阻止編寫器,而不是其他讀取器),如果需要,釋放讀鎖定並調用writeLock()以升級到寫入(從而阻止所有其他讀取和寫入)。 獲得寫鎖定后,請務必重新檢查在讀鎖定階段檢查的斷言。
除此之外,您現有的同步看起來很好。
一個想法是ReadWriteLock。 因為在這部分代碼中:
synchronized(this) {
if(registeredPatients.contains(patient)) {
return true;
}
if(waitingListPatients.contains(patient) ) {
return false;
}
//Not already registered so register or add to waiting list
return addPatient(patient);
}
您阻止訪問整個列表,即使只是讀取列表不會導致任何線程問題,但是您需要鎖定以防以后指令可以寫入。 這是由ReadWriteLock解決的,通過授予無限制的讀訪問權限,除非有人真正想寫。 這可以像這樣實現:
lock.readLock().lock();
try {
if(registeredPatients.contains(patient)) {
return true;
}
if(waitingListPatients.contains(patient) ) {
return false;
}
} finally {
lock.readLock().unlock();
}
//Not already registered so register or add to waiting list
lock.writeLock().lock();
try {
// need to re-check here, as the list could have been changed in between
if(registeredPatients.contains(patient)) {
return true;
}
if(waitingListPatients.contains(patient) ) {
return false;
}
return addPatient(patient);
} finally {
lock.writeLock().unlock();
}
現在,如果許多線程只需要讀取,但很少寫入,這將提高應用程序的速度。 如果幾乎所有讀取的線程都寫入,這實際上會減慢速度,因為您不僅需要檢查兩次,還需要鎖定兩次。 另外,synchronized比鎖更快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.