使用volatile变量停止线程

时间:2013-12-18 10:07:38

标签: java multithreading

基本上,如果我删除不必要的东西,我会有这段代码:

public class Foo {
    private volatile boolean isFinished = false;
    private long timeOut = 60 * 1000;
    ...

    // Called asynchronously from another thread
    public setFinished(boolean value) {
        isFinished = value;
    }

    public wait() {
       ...
       long start = SystemClock.uptimeMillis();
       while(!isFinished && (SystemClock.uptimeMillis() - start) <= timeOut) {
           ...
       }

       if (isFinished) {
           // Log success!!!
           ...
       }
       else {
           // Log time out!!!
           ...
       }
    }
}

此代码在95%的时间内都有效。日志文件类似于:

`wait()` is called waiting starts
`setFinished(true)` is called
`setFinished(true)` returns
"success" entry in the log

但有时,根据日志文件会发生以下情况:

`wait()` is called waiting starts
`setFinished(true)` is called
`setFinished(true)` returns
about 60 seconds pass
"time out" entry in the log

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

我唯一的猜测是这三点内部有阻止循环执行的东西:

while(!isFinished && (SystemClock.uptimeMillis() - start) <= timeOut) {
       ...
}

更新:您可能还会尝试使用System.currentTimeMillis(),因为uptimeMillis()时钟因环境变化而停止。

答案 1 :(得分:0)

如果isFinished只从false转换为true,并且如果while循环已退出,那么isFinished必须为真。

即使您未指定volatile(在实践中)也是如此,并且鉴于您指定volatile(理论上和实践中都是如此),情况肯定是这样。

因此我的猜测是第一个假设是假的。如果我是你,我会试试这个:

// Called asynchronously from another thread
public setFinished(boolean value) {
    if(!value){
        throw new AssertionError("huh?");
    }
    isFinished = value;
}

看看会发生什么。