是否正在使用低等原语如等待被认为是坏的?

时间:2015-09-29 12:50:25

标签: java multithreading future

我正在为共享计算实现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的更好选择。

3 个答案:

答案 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();

这允许您构建某种等待彼此的线程链。