在Java中等待一个事件 - 它有多难? [英] Waiting for an event in Java - how hard is it?

查看:237
本文介绍了在Java中等待一个事件 - 它有多难?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个线程不时更新它的状态,我想要一个第二个线程能够等待第一个线程完成。这样的东西:

 线程1:
while(true){
...做某事..
foo.notifyAll()
...等待一些可能永远不会发生的情况...
...
}

线程2:
...
foo.wait();
...

现在看起来不错,除非线程1的notifyAll()运行之前线程2的wait(),在这种情况下,线程2等待直到线程1再次通知(这可能永远不会发生)。



我可能的解决方案:



a)我可以使用CountDownLatch或Future,但都有一个问题,即它们本质上只运行一次。也就是说,在Thread 1的while循环中,我需要创建一个新的foo来等待每一次,Thread 2将需要询问哪个foo等待。我有一个坏的感觉,简单地写

  while(true){
foo = new FutureTask();
...
foo.set(...);
...等待可能永远不会设置的条件
...
}

因为我怕在foo = new FutureTask(),当有人等待旧的foo(因为某种原因),设置没有被调用,例如异常处理中的错误会发生什么)?



b)或者我可以使用信号量:

  class Event {
信号量sem;
Event(){sem = new Semaphore(1); sem。 }
void signal(){sem.release(); }
void reset(){sem.acquire(1); }
void wait(){if(sem.tryAcquire(1)){sem.release(); }}
}

但是我担心有一些竞争条件,如果多个线程等待(),而另一个信号()和reset()s。



问题:



Java API中没有类似于Windows事件的行为?或者,如果你鄙视Windows,像golang的WaitGroup(即CountDownLatch允许countUp())?任何东西?



如何手动执行:



线程2不能简单地等待因为虚假的唤醒和Java中没有办法知道为什么Object.wait()返回。所以我需要一个条件变量来存储事件是否发出信号。线程2:

  synchronized(foo){
while(!condition){
foo.wait );
}
}

而线程1当然会将条件设置为true同步块感谢周末的提示!



是否有现有的类包装这种行为?



或者我需要复制和粘贴代码?

解决方案

更改某些状态是标准做法执行notifyAll并在执行wait()时检查某些状态。



例如

  boolean ready = false; 

//线程1
同步(锁){
ready = true;
lock.notifyAll();
}


//线程2
同步(锁){
while(!ready)
lock.wait();
}

使用这种方法,如果线程1或线程2获取



如果您使用通知或等待而不设置值或检查值,某些编码分析工具将会发出警告。


I have a thread that updates it's state from time to time and I want a second thread to be able to wait for the first thread to be done. Something like this:

Thread 1:
    while(true) {
        ...do something...
        foo.notifyAll()
        ...wait for some condition that might never happen...
        ...
    }

Thread 2:
    ...
    foo.wait();
    ...

Now this looks nice and all unless Thread 1's notifyAll() runs before Thread 2's wait(), in which case Thread 2 waits until Thread 1 notifies again (which might never happen).

My possible solutions:

a) I could use a CountDownLatch or a Future, but both have the problem that they inherently only run once. That is, in Thread 1's while loop, I would need to create a new foo to wait for each time and Thread 2 would need to ask which foo to wait for. I have a bad feeling about simply writing

while(true) {
   foo = new FutureTask(); 
   ...
   foo.set(...);
   ...wait for a condition that might never be set...
   ...
}

as I fear that at foo = new FutureTask(), what happens when someone waited for the old foo (for "some reason", set was not called, e.g. a bug in the exception handling)?

b) Or I could use a semaphore:

class Event {
   Semaphore sem;
   Event() { sem = new Semaphore(1); sem . }
   void signal() { sem.release(); }
   void reset() { sem.acquire(1); }
   void wait() { if (sem.tryAcquire(1)) { sem.release(); } }
}

But I fear that there is some race condition, if multiple threads are wait()ing for it while another one signal()s and reset()s.

Question:

Is there nothing in the Java API that resembles the Windows Event behaviour? Or, if you despise Windows, something like golang's WaitGroup (i.e. a CountDownLatch that allows countUp())? Anything?

How to do it manually:

Thread 2 cannot simply wait because of spurious wakeup and in Java there is no way to know why Object.wait() returned. So I need a condition variable that stores whether the event is signalled or not. Thread 2:

synchronized(foo) {
    while(!condition) {
        foo.wait();
    }
}

And Thread 1 of course sets condition to true in a synchronized block. Thanks to weekens for the hint!

Is there an existing class that wraps that behaviour?

Or do I need to copy and paste the code all over?

解决方案

It is standard practice to change some state when performing notifyAll and to check some state when performing wait().

e.g.

boolean ready = false;

// thread 1
synchronized(lock) {
    ready = true;
    lock.notifyAll();
}


// thread 2
synchronized(lock) {
    while(!ready) 
        lock.wait();
}

With this approach, it doesn't matter if thread 1 or thread 2 acquires the lock first.

Some coding analysis tools will give you a warning if you use notify or wait without setting a value or checking a value.

这篇关于在Java中等待一个事件 - 它有多难?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆