Java 从EDT传递数据:是否需要volatile?
我有一个后台线程,它在Java 从EDT传递数据:是否需要volatile?,java,thread-safety,Java,Thread Safety,我有一个后台线程,它在start变量变为true之前不会开始处理: class MyBackgroundThread implements Runnable { // ... public void run() { while(true) { if(!start) continue; doSomethingWith(myValue); } } } 通过单击JFrame上的按钮,可以将st
start
变量变为true
之前不会开始处理:
class MyBackgroundThread implements Runnable {
// ...
public void run() {
while(true) {
if(!start) continue;
doSomethingWith(myValue);
}
}
}
通过单击
JFrame
上的按钮,可以将start
变量设置为true,当然,JFrame在事件调度线程上运行。后台线程类中还有一个myValue
字段,可通过单击按钮进行设置:
startBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
backgroundThreadInstance.setMyValue(100);
backgroundThreadInstance.setStart(true);
// ...
}
});
如您所见,在将
start
设置为true
之前,它会为myValue
赋值。这是否意味着不需要将myValue
和start
设置为volatile
?由于myValue
是先写入的,因此它将在start
之前泄漏到后台线程,因此后台线程永远不会有机会处理未初始化的myValue
?简短回答是肯定的。虽然,在实践中,你的线程可能最终会看到变为true的情况,但理论上它可能永远不会发生
但是,同意@NamshubWriter的观点,有比忙/闲循环更好的方法来实现这一点。我喜欢他的建议,设置整数,然后将其提交给ExecutorService。e、 g
public void actionPerformed(ActionEvent e) {
BackgroundRunnableInstance runnable = new BackgroundRunnableInstance();
runnable.setMyValue(100); // could be in the constructor instead
someExecutorService.submit(runnable);
}
一个区别是,如果他们多次按下按钮,就会启动多个Runnable。这可能是您想要的,也可能不是您想要的。与其在
MyBackgroundThread
中进行您自己的旋转循环,为什么不使用CountDownLatch
?更好的是,为什么不创建一个实现Runnable
的类,并在actionPerformed()
中创建一个构造函数,该构造函数接受一个整数并将其传递给ExecutorService
?start
变量仍然在两个线程之间共享:EDT
和MyBackgroundThread
。因此,为了确保EDT
中start
的更改值确实反映在mybackgroundthread
中,您应该在声明start
变量时使用volatile
关键字。