Java Equivalent.NET ManualResetEvent и WaitHandle
Я хотел бы знать, поддерживает ли Java эквивалент классов .NET ManualResetEvent и WaitHandle, так как я бы хотел написать код, который блокирует данный тайм-аут, если событие не инициировано.
.NET-классы WaitHandle и ManualResetEvent обеспечивают приятный, беспроблемный интерфейс для того, что также является потокобезопасным, насколько я знаю, поэтому что может предложить Java?
Ответы
Ответ 1
Считаете ли вы использование wait
/notify
(эквивалент Monitor.Wait
и Monitor.Pulse
) вместо?
Вам нужно немного проверить, действительно ли вам нужно ждать (чтобы избежать условий гонки), но он должен работать.
В противном случае что-то вроде CountDownLatch
может сделать то, что вы хотите.
EDIT: Я только заметил, что CountDownLatch
в основном "одноразовый" - вы не можете reset подсчитать позже, насколько я могу видеть. Возможно, вы захотите Semaphore
. Используйте tryAcquire
, чтобы подождать с таймаутом:
if (semaphore.tryAquire(5, TimeUnit.SECONDS)) {
...
// Permit was granted before timeout
} else {
// We timed out while waiting
}
Обратите внимание, что это отличается от ManualResetEvent
тем, что каждый успешный вызов tryAcquire
уменьшает количество разрешений, поэтому в итоге они снова закончатся. Вы не можете сделать это надолго "установленным", как вы могли, с помощью ManualResetEvent
. (Это будет работать с CountDownLatch
, но тогда вы не смогли бы "reset":)
Ответ 2
class ManualResetEvent {
private final Object monitor = new Object();
private volatile boolean open = false;
public ManualResetEvent(boolean open) {
this.open = open;
}
public void waitOne() throws InterruptedException {
synchronized (monitor) {
while (open==false) {
monitor.wait();
}
}
}
public void set() {//open start
synchronized (monitor) {
open = true;
monitor.notifyAll();
}
}
public void reset() {//close stop
open = false;
}
}
Ответ 3
От: http://www.experts-exchange.com/Programming/Languages/Java/Q_22076798.html
Привет, вы можете добиться синхронизации, используя класс java.util.concurrent.Semaphore(используйте разрешение 0).
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Semaphore.html
Пример ниже показывает, как решить первую проблему с синхронизацией, другая будет похожа:
import java.util.concurrent.Semaphore;
class ScalesCommunication {
private static Semaphore sem = new Semaphore(0);
// called by thread 1
void readLoop() {
//...
//after connection established, release semaphore (value incremented by 1)
sem.release();
}
// called by thread 2
String sendCommand(String command) {
sem.acquire(); // thread waits here if sem value == 0
// at this point connection is established
//...
}
}
Ответ 4
В теории класс ManualResetEvent, как указано выше, верен на Java 5 (но не ранее). Учитывая долгую историю неправильных (или неадекватных) реализаций изменчивости, мне кажется разумнее добавить дополнительный синхронизированный блок в reset(), чтобы создать гарантированный барьер записи и обеспечить полную атомарность. Опасность состоит в том, что чтение "открытого" может передать запись "открытого" на многопроцессорном процессоре Intel. Преимущество приведенного ниже изменения: оно может оказаться неэффективным, но оно имеет большое преимущество, гарантируемое быть неправым, при очень небольших дополнительных затратах.
class ManualResetEvent {
private final Object monitor = new Object();
private volatile boolean open = false;
public ManualResetEvent(boolean open) {
this.open = open; }
public void waitOne() throws InterruptedException {
synchronized (monitor) {
while (open==false) {
monitor.wait();
}
}
}
public void set() {//open start
synchronized (monitor) {
open = true;
monitor.notifyAll();
}
}
public void reset() {//close stop
synchronized(monitor) {
open = false;
}
}
}
Благодаря оригинальному плакату.