对于大学作业,我需要实施医院病人等待系统的一部分。系统使用等待名单上的患者集合,以及在特定时期(例如今年)注册操作的一组患者。
我已经使用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;
}
}
答案 0 :(得分:1)
您这里只有一些代码,但您的同步看起来不错。
仅供参考,您的LinkedList.contains
需要O(n)
。我会做以下其中一个
使用具有常量查找的LinkedHashSet
,但保持顺序。但是,根据您以后的使用情况,这可能不太令人满意。
使用HashSet
来扩充您的LinkedList
。检查LinkedList
。
.contains()
醇>
答案 1 :(得分:1)
您可以考虑读/写锁...但选择这取决于您对用户只阅读收藏的频率的期望,而不是阅读和写作。
一个。用户尝试添加已存在的患者的次数(阅读)
B中。您是否经常阅读上面未显示的应用程序其他部分的列表(阅读)
℃。用户成功添加患者的次数(读取+写入)
如果与C相比(A + B)很大,请考虑像java.util.concurrent.locks.ReentrantReadWriteLock
这样的读/写锁定。调用readLock()开始读取(只阻止编写器,而不是其他读取器),如果需要,释放读锁定并调用writeLock()以升级到写入(从而阻止所有其他读取和写入)。获得写锁定后,请务必重新检查在读锁定阶段检查的断言。
除此之外,您现有的同步看起来还不错。
答案 2 :(得分:0)
一个想法是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比锁定更快。