我正在为共享计算实现Future
接口。即一个线程执行计算,而其他线程需要相同的结果,只需通过Future
请求它。所以,我已经阅读了Object#wait()方法文档,并认为它完全满足了我的需求。以下是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
}
由于依赖于低级原语,我不确定实现是否良好。我认为,根据经验,我们应该避免使用这种低级原语。也许这就是合理的情况。
也许wait()
中有java.util.concurrent
的更好选择。
答案 0 :(得分:5)
使用低级同步功能也不错。
在您的代码中我看不到通知。如果你进去等待另一个线程需要通知唤醒等待线程。
如果waitForTheResult
是私有Object
,可能无法从外部访问,那么在计算结果时如何实施通知?
答案 1 :(得分:1)
一般来说,使用原语并不是一个坏习惯。它总是取决于你使用它的是什么。原语和非原语之间的重要区别在于原语永远不会为空(它们不是类的实例)。
因此,例如,如果您有boolean primitiveBool;
,则primitiveBool
为false(默认值)。
但如果是Boolean nonPrimitiveBool;
,nonPrimitiveBool
默认为null
。
另一种情况:Boolean anotherBool = Boolean.TRUE;
- 这是使用非基元的正确方法(该值是非原始的真实)。
答案 2 :(得分:1)
我现在有两种方式可以使用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();
这允许您构建某种等待彼此的线程链。