等待对象初始化

时间:2014-05-30 15:57:16

标签: java wait

我有一个在单独的线程中初始化的对象。在填充本地数据库时,初始化可能需要几秒钟。

SpecialAnalysis currentAnalysis = new SpecialAnalysis(params_here);

我试图实施"取消"按钮,用于将对象的isCancelled布尔值设置为true。实现这个的正确Java方法是什么?

while (currentAnalysis == null) {
}
currentAnalysis.cancel();

此方法冻结程序,因为它似乎已进入计算效率低下的循环。这是我可以使用Object.wait()吗?

的情况

我目前的糟糕/半成功解决方案是:

while (currentAnalysis == null) {
    Thread.sleep(500);
}
currentAnalysis.cancel();

谢谢!

2 个答案:

答案 0 :(得分:7)

首先,是Object.wait()Object.notify() / Object.notifyAll()是您所需要的。你是否直接使用它们是另一回事。由于使用wait/notify直接编程容易出错,通常建议使用concurrency tools added in Java 1.5(请参阅下面的第二种方法)。


传统的wait/notify方法:

初​​始化:

    synchronized (lockObject) {
        SpecialAnalysis currentAnalysis = new SpecialAnalysis(params_here);
        lockObject.notifyAll();
    }

取消'螺纹:

    synchronized (lockObject) {
        while (currentAnalysis == null) {
            try { lockObject.wait(); }
            catch Exception(e) { } // FIXME: ignores exception
        }
    }
    currentAnalysis.cancel();

当然,这些可以是同步方法而不是块。您选择的lockObject将取决于取消'取消'您需要的线程等。理论上它可以是任何东西,即Object lockObject = new Object();,只要您小心正确的线程可以访问它。

请注意,由于spurious wakeups可能来自底层操作系统,因此在此处调用wait()非常重要。


更简单的方法是使用CountDownLatch,免除wait()& notify()的细节:

(我在这里做了几个假设,以便提出一个可能更清晰的方法)。

    class AnalysisInitialiser extends Thread {

        private CountDownLatch cancelLatch = new CountDownLatch(1);
        private SpecialAnalysis analysis = null;

        @Override
        public void run() {
            analysis = new SpecialAnalysis(params);
            cancelLatch.countDown();
        }

        public SpecialAnalysis getAnalysis() {
            cancelLatch.await();
            return analysis;
        }
    }

然后在需要发送取消信号的线程中:(显然你需要以某种方式获取AnalysisInitialiser对象)

    analysisInit.getAnalysis.cancel();

没有并发原语样板,耶!

答案 1 :(得分:-1)

我喜欢这个问题所以投票了。

你可以这样做

    do {
    if(currentAnalysis != null){
    currentAnalysis.cancel();
    }
   }
     while (currentAnalysis == null)

此处,do一直在检查currentAnalysis的价值,一旦not nullcancel执行looping,其他人保持currentAnalysis并检查{{1}}值。

这是我现在找到的一种更好的方法