以下代码可以使用,但我稍微不得不编写isRunning()方法:
class Test {
private boolean running;
public void startX() {
synchronized(this) {
running = true
}
while (isRunning()) {
//do something
}
}
public synchronized void stopX() {
running = false;
}
private synchronized boolean isRunning() {
return running;
}
}
我可以用其他方式同步running
中while (running){}
变量的读取,还是必须编写isRunning()方法?同样的问题也适用于其他控制变量,例如
for (;running;) {}
或
if (running) {}
在所有这些情况下,似乎你被迫编写一个无意义的方法来使同步正确。我错过了什么吗?
答案 0 :(得分:3)
如果您只是将running
的值重置一次以指定停止,则可以使用volatile
关键字。
然而,如果你需要多次启动和停止,这不会起作用。这是因为易失性字段"可能会错过更新"
这里有一个链接,说明volatile
在link
这里是来自该链接的代码示例,因为它已经死了:
public class StoppableTask extends Thread {
private volatile boolean pleaseStop;
public void run() {
while (!pleaseStop) {
// do some stuff...
}
}
public void tellMeToStop() {
pleaseStop = true;
}
}
如果需要多次启动和停止,则需要使用其中一个Java 5并发锁定对象或显式同步
答案 1 :(得分:2)
您可以将运行字段设置为volatile。使字段变为volatile会使JVM注意到它应该对其他线程可见的该字段进行更改。 "错过更新"警告是针对您想要读取值并根据该值更新的情况,这在这里似乎不适用。 多个线程可以写入此字段,如果他们所做的只是设置一个布尔标志,那么这不会成为问题。
或者,如果您尝试取消某个帖子,那么Thread上已经提供了一个等效标志(并且可以解决可见性问题)。您可以在线程上调用中断,Runnable中的代码可以查询Thread.currentThread().isInterrupted()
以判断它是否被中断。这比使用自己的标志更可取,因为中断将导致线程在等待或休眠时唤醒。有了自己的旗帜,你必须等到控制到达可以测试旗帜的地方。
答案 2 :(得分:0)
只是为了补充其他人提出的建议Repeater
。
或者,您可以为检查创建一个类。
我已将变量设为volatile
,因此所有线程都将指向同一对象。
static
注意:强>
如果您不需要全局变量,请删除class Runner{
boolean static running=true;
public static synchronized boolean getRunning(){
return running;
}
public static synchronized boolean setRunning(boolean r){
running=r;
}
}