复制服务和同步

duplication service and synchronized

开始TimeThread.java里面的Service.java 重复运行 Service.java 时会出现问题。

为什么 'isWait' 值在 'Log.d("isRun1")' 中为真而在 'Log.d("isRun2")' 中为假?

我想知道 'duplicate running of service' 和 'synchronized'。

我的代码是:

Service.java

thread.pauseNrestart(false);

Thread.java

    public class TimeThread extends Thread {

Handler handler;
boolean isRun = true;
boolean isWait = false;

public TimeThread(Handler handler) {
    this.handler = handler;
}

public void pauseNResume(boolean isWait) {

    synchronized (this) {

        this.isWait = isWait;
            *Log.d("isRun1 :" + isRun + "");*
        notify();
    }
}

public void run() {
    while (isRun) {
         *Log.d("isRun2 :" + isRun + "");*
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            // TODO: handle exception
        }
        if (isWait) {
            try {
                synchronized (this) {
                    wait();
                }
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
        handler.sendEmptyMessage(0);
    }
}

}

某些代码行可能会在进行优化时重新排序:
- 编译器在编译时通过重新排序来优化代码;
- JVM 可以通过重新排序来动态优化代码;
- 硬件可能会通过重新排序来优化性能。

所以代码段:

this.isWait = isWait;
*Log.d("isRun1 :" + isRun + "");*

可能换行了。

这也可能归结为可见性问题。有时效果可能对其他线程不可见。

检查您的 while 循环时,您不在同步部分,因此如果 pauseNResume 在别处调用,事情可能同时发生变化。如前所述,线程也可能不会立即看到这些更改。

尝试将 isRun 和 isWait 声明为易变的? Volatile 将保证对该变量的读写不会被重新排序。这将解决我指出的上述代码部分的行是否被切换的问题,因此打印将始终在 isWait 变量更改后发生。

但是,对于您在 while 循环条件检查中使用这些布尔值的方式,我建议您也使用 AtomicBoolean 而不是普通布尔值。