Java wait()和notifyAll()恢复最早的线程

Java wait()和notifyAll()恢复最早的线程,java,concurrency,thread-safety,Java,Concurrency,Thread Safety,我的问题是: 假设我有一个类A,带有一些变量A 类B和变量prev和next 在类A中,我想使方法changeIfEqual(B myB)检查A.A==my_B.prev,如果是,我将A.A更改为my_B.next。但是如果A.A!=my_B.prev我希望线程等待()直到continion为true,然后执行等待时间最长的线程 所以我想A.changeIfEqual(B myB)应该是这样的: public synchronized void changeIfEqual(B myB){ w

我的问题是:

假设我有一个类
A
,带有一些变量
A

B
和变量
prev
next

在类
A
中,我想使方法
changeIfEqual(B myB)
检查
A.A==my_B.prev
,如果是,我将
A.A
更改为
my_B.next
。但是如果
A.A!=my_B.prev
我希望线程
等待()
直到continion为true,然后执行等待时间最长的线程

所以我想
A.changeIfEqual(B myB)
应该是这样的:

public synchronized void changeIfEqual(B myB){
  while(this.a != myB.b_prev){
     wait();
  }
  notifyAll();
}

在这种情况下,问题是如何确保恢复最旧的线程?(
wait()
notifyAll()
不提供该选项)

您不需要。哪个线程得到通知取决于调度程序。如果用ReentrantLock替换隐式锁(使用synchronized),则可以指定该锁是公平的。但这不是一个完美的解决方案,请参见:

此类的构造函数接受可选的公平性参数。当设置为true时,在争用下,锁有利于向等待时间最长的线程授予访问权限。否则,此锁不保证任何特定的访问顺序。与使用默认设置的程序相比,使用由多个线程访问的公平锁的程序可能显示较低的总体吞吐量(即较慢;通常较慢),但在获得锁和保证无饥饿的时间上差异较小。但是请注意,锁的公平性并不能保证线程调度的公平性。因此,使用公平锁的多个线程中的一个线程可能会连续多次获得公平锁,而其他活动线程则没有进行,并且当前没有持有该锁。还要注意,untimed tryLock方法不支持公平性设置。如果锁可用,即使其他线程正在等待,它也会成功


如果您绝对必须按照特定顺序唤醒“消费者”线程,*要做的事情是为每个消费者提供自己的
信号量
,并让每个消费者在等待它之前将对其信号量的引用放入队列中

class MyConsumer {
    private final Queue<Semaphore> sleep_q;
    private final Semaphore sleep_sem = new Semaphore(0);

    public MyConsumer(Queue sleep_q) {
        this.sleep_q = sleep_q;
    }

    private void waitToBeNotified() {
        sleep_q.add(sleep_sem);
        sleep_sem.acquire();
    }

    public void whatever() {
        doSomeStuff();
        waitToBeNotified();
        doSomeMoreStuff();
}
类支原体{
专用最终队列睡眠;
私有最终信号量sleep_sem=新信号量(0);
公共消费者(队列睡眠){
this.sleep\u q=sleep\u q;
}
私有void waitToBeNotified(){
睡眠质量添加(睡眠扫描电镜);
睡眠获得;
}
公共空间{
doSomeStuff();
waitToBeNotified();
doSomeMoreStuff();
}
生产者可以通过从队列中弹出一个信号量并释放一个许可证来唤醒等待时间最长的线程

class MyProducer {
    private final Queue<Semaphore> sleep_q;

    public MyConsumer(Queue sleep_q) {
        this.sleep_q = sleep_q;
    }

    public void goForthAndProduceStuff() {
        while (...) {
            produceSomething();
            awakenAConsumer();
        }
    }

    private void awakenAConsumer() {
        Semaphore sem = sleep_q.poll();
        if (sem != null) {
            sem.release();
        }
    }

}
类MyProducer{
专用最终队列睡眠;
公共消费者(队列睡眠){
this.sleep\u q=sleep\u q;
}
GofortHandProductStuff()的公共无效信息{
而(…){
生产某物();
唤醒消费者();
}
}
私人消费者{
信号量sem=sleep_q.poll();
如果(sem!=null){
sem.release();
}
}
}


*但是,请参阅我对原始问题的评论。

如果您有多个线程都在等待同一事件,那么在事件发生时唤醒哪一个线程并不重要。如果它确实重要,那么您的问题解决方案可能比需要的更复杂。是的,但这远远超出了原始问题。@edharned,回答OP的问题而不说“远远超过”的唯一方法就是简单地说:“不行!对不起,祝你愉快!”但是,OP试图解决一个问题。在我看来,这可能是一个问题,但不是一个难题。只是为了咧嘴一笑,我想我会展示我将如何解决它。