我有一个在一个单独的线程中初始化的对象.在填充本地数据库时,初始化可能需要几秒钟.
SpecialAnalysis currentAnalysis = new SpecialAnalysis(params_here);
Run Code Online (Sandbox Code Playgroud)
我正在尝试实现一个"取消"按钮,它将对象的isCancelled布尔值设置为true.实现这个的正确Java方法是什么?
while (currentAnalysis == null) {
}
currentAnalysis.cancel();
Run Code Online (Sandbox Code Playgroud)
该方法冻结了程序,因为它似乎进入了计算效率低下的循环.这是我可以使用的情况Object.wait()吗?
我目前的糟糕/半成功的解决方案是:
while (currentAnalysis == null) {
Thread.sleep(500);
}
currentAnalysis.cancel();
Run Code Online (Sandbox Code Playgroud)
谢谢!
首先,是Object.wait()和Object.notify()/ Object.notifyAll()是你需要的.你是否直接使用它们是另一回事.由于易于编程,wait/notify因此通常建议使用Java 1.5中添加的并发工具(参见下面的第二种方法).
传统wait/notify方法:
初始化:
synchronized (lockObject) {
SpecialAnalysis currentAnalysis = new SpecialAnalysis(params_here);
lockObject.notifyAll();
}
Run Code Online (Sandbox Code Playgroud)
在'取消'主题中:
synchronized (lockObject) {
while (currentAnalysis == null) {
try { lockObject.wait(); }
catch Exception(e) { } // FIXME: ignores exception
}
}
currentAnalysis.cancel();
Run Code Online (Sandbox Code Playgroud)
当然,这些可以是同步方法而不是块.您的选择lockObject将取决于您需要多少"取消"线程等.理论上它可以是任何东西,即Object lockObject = new Object();只要您小心正确的线程可以访问它.
请注意,wait()由于可能存在来自底层OS 的虚假唤醒,因此将调用置于此处的while循环中非常重要.
一个更简单的方法是使用a 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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后在需要发送取消信号的线程中:(显然你需要以AnalysisInitialiser某种方式获取对象)
analysisInit.getAnalysis.cancel();
Run Code Online (Sandbox Code Playgroud)
没有并发原语样板,耶!
| 归档时间: |
|
| 查看次数: |
4555 次 |
| 最近记录: |