此对象是否在侦听器线程安全中修改?
Is this object modified in listener threadsafe?
在以下代码段中,假设有两个线程 read/write from/to results
。当 eventListener
线程写入 results
时,被阻塞的线程是否能够访问最新的结果?如果没有,什么实用程序(volatile
、AtomicReference
)会有帮助?
private Object doStuff() {
CountDownLatch latch = new CountDownLatch( 1 );
Object[] results = new Object[1];
EventObjectListener eventListener = ( String topic, Object eventObject ) -> {
results[0] = eventObject;
latch.countDown();
};
eventReceiver.addEventListener( eventListener );
doThingThatGeneratesEvent();
int waitMagnitude = 10;
TimeUnit waitUnit = TimeUnit.SECONDS;
try {
latch.await( waitMagnitude, waitUnit );
} catch ( InterruptedException e ) {
return null;
} finally {
eventReceiver.removeEventListener( eventListener );
}
return results[0];
}
是的,CountDownLatch
保证可见性¹,所以如果 await
没有超时,results[0]
就可以了。然而,代码可能会被重写得更清晰一些。
¹ 即所有来自 countDown()
happen before 另一个线程 returns 之前的线程的所有写入来自 await()
调用。
一个稍微更清晰的(恕我直言)版本将使用CompletableFuture
如下:
CompletableFuture<Object> future = new CompletableFuture();
EventObjectListener eventListener = (topic, eventObject) ->
future.complete(eventObject);
try {
return future.get(waitMagnitude, waitUnit);
} catch(Exception e) {
return null;
} finally {
eventReceiver.removeEventListener(eventListener);
}
在以下代码段中,假设有两个线程 read/write from/to results
。当 eventListener
线程写入 results
时,被阻塞的线程是否能够访问最新的结果?如果没有,什么实用程序(volatile
、AtomicReference
)会有帮助?
private Object doStuff() {
CountDownLatch latch = new CountDownLatch( 1 );
Object[] results = new Object[1];
EventObjectListener eventListener = ( String topic, Object eventObject ) -> {
results[0] = eventObject;
latch.countDown();
};
eventReceiver.addEventListener( eventListener );
doThingThatGeneratesEvent();
int waitMagnitude = 10;
TimeUnit waitUnit = TimeUnit.SECONDS;
try {
latch.await( waitMagnitude, waitUnit );
} catch ( InterruptedException e ) {
return null;
} finally {
eventReceiver.removeEventListener( eventListener );
}
return results[0];
}
是的,CountDownLatch
保证可见性¹,所以如果 await
没有超时,results[0]
就可以了。然而,代码可能会被重写得更清晰一些。
¹ 即所有来自 countDown()
happen before 另一个线程 returns 之前的线程的所有写入来自 await()
调用。
一个稍微更清晰的(恕我直言)版本将使用CompletableFuture
如下:
CompletableFuture<Object> future = new CompletableFuture();
EventObjectListener eventListener = (topic, eventObject) ->
future.complete(eventObject);
try {
return future.get(waitMagnitude, waitUnit);
} catch(Exception e) {
return null;
} finally {
eventReceiver.removeEventListener(eventListener);
}