我有一个在一个单独的线程中初始化的对象.在填充本地数据库时,初始化可能需要几秒钟.
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 次 |
最近记录: |