使用诸如 wait 之类的低级原语是否被认为是不好的?
Is using of low-level primitives such as wait considered bad?
我正在为共享计算实现 Future
接口。 IE。一个线程执行计算,其他线程需要相同的结果,只需通过 Future
请求即可。所以,我读过 Object#wait() method documentation and decided that it perfectly satisfies my needs. Here's how my implementation of the Future#get() 方法看起来:
public class CustomFuture implements Future<Collection<Integer>> {
private AtomicBoolean started;
private Exception computationException;
private boolean cancelled;
private Collection<Integer> computationResult;
private Object waitForTheResult = new Object();
public Collection<Integer> get(){
if(started.compareAndSet(false, true))
//start the computation //notifyAll() is called after finishing the computation here.
while(computationResult == null){
if(cancelled)
throw new CancellationException();
if(computationException != null)
throw new ExectuonException();
synchronized(waitForTheResult){
waitForTheResult.wait();
}
}
return computationResult;
}
//The rest of methods
}
我不确定实现是否良好,因为依赖于低级原语。我认为,根据经验,我们应该避免使用这种低级原语。或许这才是情理之中吧。
也许 java.util.concurrent
中有 wait()
更好的选择。
不用低级同步函数也不错
在您的代码中我没有看到通知。如果您进入等待状态,则需要通知另一个线程来唤醒等待中的线程。
如果waitForTheResult
是私有的Object
可能无法从外部访问,那么计算结果时如何实现通知?
一般来说,使用基元并不是一个坏习惯。它总是取决于你用它做什么。基元和非基元之间的重要区别在于基元永远不会为空(它们不是 class 的实例)。
因此,例如,如果您有 boolean primitiveBool;
,primitiveBool
为 false(默认值)。
但在 Boolean nonPrimitiveBool;
的情况下,nonPrimitiveBool
默认为 null
。
另一种情况:Boolean anotherBool = Boolean.TRUE;
- 这是使用非原始值的正确方法(值为非原始值 true)。
我现在有两种方法可以使用 java.util.concurrent
中的设施:
如果您想从主线程收集数据,您可以使用 Java 中的 ExecutorCompletionService
。只需将每个 Future 提交给服务并等待完成并收集结果。
ExecutorService ex = Executors.newFixedThreadPool(MAX_THREADS);
ExecutorCompletionService<MyResults> ecs = new ExecutorCompletionService<MyResults>(ex);
ecs.submit(new MyWorker());
ex.shutdown();
ex.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
for (int x = 0; x < NUM_TASKS; ++x) {
MyResult sr = ecs.take().get();
}
另一种方法是使用 ReentrantLock
,这是一个线程安全锁,它可以由一个线程获取并且允许其他线程不必等待锁再次解锁
ReentrantLock lock = new ReentrantLock();
// thread one
if(lock.tryLock(Long.MAX_VALUE, TimeUnit.SECONDS)){
// aquire lock
lock.lock();
// do computation
}
// after computation
lock.unlock();
// Thread two
if(lock.tryLock(Long.MAX_VALUE, TimeUnit.SECONDS)){
// get results
lock.lock();
}
// after computation
lock.unlock();
这允许您构建某种相互等待的线程链。
我正在为共享计算实现 Future
接口。 IE。一个线程执行计算,其他线程需要相同的结果,只需通过 Future
请求即可。所以,我读过 Object#wait() method documentation and decided that it perfectly satisfies my needs. Here's how my implementation of the Future#get() 方法看起来:
public class CustomFuture implements Future<Collection<Integer>> {
private AtomicBoolean started;
private Exception computationException;
private boolean cancelled;
private Collection<Integer> computationResult;
private Object waitForTheResult = new Object();
public Collection<Integer> get(){
if(started.compareAndSet(false, true))
//start the computation //notifyAll() is called after finishing the computation here.
while(computationResult == null){
if(cancelled)
throw new CancellationException();
if(computationException != null)
throw new ExectuonException();
synchronized(waitForTheResult){
waitForTheResult.wait();
}
}
return computationResult;
}
//The rest of methods
}
我不确定实现是否良好,因为依赖于低级原语。我认为,根据经验,我们应该避免使用这种低级原语。或许这才是情理之中吧。
也许 java.util.concurrent
中有 wait()
更好的选择。
不用低级同步函数也不错
在您的代码中我没有看到通知。如果您进入等待状态,则需要通知另一个线程来唤醒等待中的线程。
如果waitForTheResult
是私有的Object
可能无法从外部访问,那么计算结果时如何实现通知?
一般来说,使用基元并不是一个坏习惯。它总是取决于你用它做什么。基元和非基元之间的重要区别在于基元永远不会为空(它们不是 class 的实例)。
因此,例如,如果您有 boolean primitiveBool;
,primitiveBool
为 false(默认值)。
但在 Boolean nonPrimitiveBool;
的情况下,nonPrimitiveBool
默认为 null
。
另一种情况:Boolean anotherBool = Boolean.TRUE;
- 这是使用非原始值的正确方法(值为非原始值 true)。
我现在有两种方法可以使用 java.util.concurrent
中的设施:
如果您想从主线程收集数据,您可以使用 Java 中的 ExecutorCompletionService
。只需将每个 Future 提交给服务并等待完成并收集结果。
ExecutorService ex = Executors.newFixedThreadPool(MAX_THREADS);
ExecutorCompletionService<MyResults> ecs = new ExecutorCompletionService<MyResults>(ex);
ecs.submit(new MyWorker());
ex.shutdown();
ex.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
for (int x = 0; x < NUM_TASKS; ++x) {
MyResult sr = ecs.take().get();
}
另一种方法是使用 ReentrantLock
,这是一个线程安全锁,它可以由一个线程获取并且允许其他线程不必等待锁再次解锁
ReentrantLock lock = new ReentrantLock();
// thread one
if(lock.tryLock(Long.MAX_VALUE, TimeUnit.SECONDS)){
// aquire lock
lock.lock();
// do computation
}
// after computation
lock.unlock();
// Thread two
if(lock.tryLock(Long.MAX_VALUE, TimeUnit.SECONDS)){
// get results
lock.lock();
}
// after computation
lock.unlock();
这允许您构建某种相互等待的线程链。