调用者阻塞直到 getFoo() 准备好一个值?
我有一个 Java Thread
,它公开了其他线程想要访问的属性:
I have a Java Thread
which exposes a property which other threads want to access:
class MyThread extends Thread {
private Foo foo;
...
Foo getFoo() {
return foo;
}
...
public void run() {
...
foo = makeTheFoo();
...
}
}
问题是从它运行到 foo
可用需要很短的时间.调用者可以在此之前调用 getFoo()
并获得 null
.我宁愿他们在初始化发生后简单地阻塞、等待并获取值.(foo
之后永远不会改变.)它准备好需要几毫秒,所以我对这种方法很满意.
The problem is that it takes some short time from the time this runs until foo
is available. Callers may call getFoo()
before this and get a null
. I'd rather they simply block, wait, and get the value once initialization has occurred. (foo
is never changed afterwards.) It will be a matter of milliseconds until it's ready, so I'm comfortable with this approach.
现在,我可以使用 wait()
和 notifyAll()
实现这一点,并且有 95% 的机会我会做对.但我想知道你们会怎么做;java.util.concurrent
中是否有一个原语可以做到这一点,我错过了?
Now, I can make this happen with wait()
and notifyAll()
and there's a 95% chance I'll do it right. But I'm wondering how you all would do it; is there a primitive in java.util.concurrent
that would do this, that I've missed?
或者,您将如何构建它?是的,让 foo
易变.是的,在内部锁 Object
上同步并将检查放入 while
循环,直到它不是 null
.我错过了什么吗?
Or, how would you structure it? Yes, make foo
volatile. Yes, synchronize on an internal lock Object
and put the check in a while
loop until it's not null
. Am I missing anything?
推荐答案
如果 foo
只初始化一次,则 CountDownLatch
非常适合.
If foo
is initialized only one time, a CountDownLatch
is a great fit.
class MyThread extends Thread {
private final CountDownLatch latch = new CountDownLatch(1);
...
Foo getFoo() throws InterruptedException
{
latch.await(); /* Or use overload with timeout parameter. */
return foo;
}
@Override
public void run() {
foo = makeTheFoo()
latch.countDown();
}
}
闩锁提供与 volatile
关键字相同的可见性行为,这意味着读取线程将看到线程分配的 foo
的值,即使 foo
未声明为 volatile
.
Latches provide the same visibility behavior as the volatile
keyword, meaning that reading threads will see the value of foo
assigned by the thread, even though foo
isn't declared volatile
.
相关文章