Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 简单的LinkedList和队列同步_Java_Multithreading_Concurrency - Fatal编程技术网

Java 简单的LinkedList和队列同步

Java 简单的LinkedList和队列同步,java,multithreading,concurrency,Java,Multithreading,Concurrency,对于大学作业,我需要实施医院患者等待系统的一部分。该系统使用等待名单上的患者集合,以及在指定期间(例如今年)注册手术的一组患者 我使用HashSet和LinkedList实现了如下所需的方法。该方法几乎是完全同步的,所以我想知道是否有一种更有效的实现,使用更少的同步,或者使用锁进行更细粒度的读写同步 public Class OperationPeriod { ... private Set<Patient> registeredPatients=new HashSet<Pat

对于大学作业,我需要实施医院患者等待系统的一部分。该系统使用等待名单上的患者集合,以及在指定期间(例如今年)注册手术的一组患者

我使用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;
    }
}
公共类操作周期{
...
private Set registeredPatients=new HashSet();
私有集合waitingListPatients=new LinkedList();
私人int能力;
...
公共布尔bookOperation(患者){
如果(!手术检查测量要求(患者)){
返回false;
}
//病人可能已经登记了
已同步(此){
if(注册患者。包含(患者)){
返回true;
}
if(waitingListPatients.contains(患者)){
返回false;
}
//尚未注册,因此请注册或添加到等待列表中
返回患者(患者);
}
}
私人病人(病人){
if(registeredPatients.size()<容量){
登记患者。添加(患者);
返回true;
}
否则{
waitingListPatients.add(患者);
返回false;
}
}

此处只有部分代码,但同步效果良好

仅供参考,您的
链接列表。包含
获取
O(n)
。我将执行以下操作之一

  • 使用一个
    LinkedHashSet
    ,它具有不断的查找功能,但可以保持顺序。但是,根据您以后的使用情况,这可能并不令人满意

  • 使用
    HashSet
    来扩充您的
    LinkedList
    。使用
    LinkedList
    除非选中
    .contains()


  • 你可以考虑读/写锁……但是选择它取决于你对用户将只阅读集合的次数的期望,而不是读和写。

    A.用户尝试添加已存在患者的次数(读取)

    B.您从上面未显示的应用程序的另一部分读取列表的频率(阅读)

    C.用户成功添加患者的次数(读+写)

    如果(A+B)与C相比是巨大的,那么考虑一个读/写锁,比如“代码> java .UTI.O.Out.Cord.ReEntReTrAdRead Loope< /COD>。(从而阻止所有其他读写操作)。获得写锁后,请确保重新检查在读锁阶段检查的断言


    除此之外,您现有的同步看起来还不错。

    一个想法是读写锁。因为在这部分代码中:

    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();
    }
    

    现在,如果许多线程只需要读取,而很少写入,这将提高应用程序的速度。如果几乎所有读取和写入的线程都需要写入,这实际上会降低速度,因为您不仅需要检查两次,还需要锁定两次。此外,同步比锁定快。

    LinkedHashSet是一个非常好的idea、 感谢您指出这一点。它还提供了持续删除功能,这在取消患者预约时非常有用。为什么您说它可能不适合其他用途?您的意思是队列是否需要按照与插入顺序不同的顺序进行排序,例如自然顺序?或者如果我希望重新插入一个元素(无需删除和重新插入)在队列中的稍后点?@user2977365,如果您打算将其用作FIFO队列,它将非常有效(创建迭代器,调用
    next
    ,然后调用
    remove
    )。如果您需要LinkedList的所有功能,如FILO队列,那么它不是一个好的选择。读/写锁只有在读比写多得多的情况下才真正有用。这就是为什么Java的同步集合不使用它们()我认为这是一个很好的解释。感谢您的澄清,我认为这是事实,但对实施不完全有信心。就目前而言,在我的应用程序(a+B)中