我有以下代码:
public class ThreadTest implements Runnable {
public int ThrCount = 0;
public void ThrCountIncr() {
while (true) {
ThrCount++;
System.out.println(ThrCount);
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void run() {
while (true) {
if (ThrCount > 10) {
System.out.println(ThrCount + "\n Thread finished");
System.exit(1);
}
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
但是当我从run
删除此行时,它会停止工作:
Thread.currentThread().sleep(100);
首先,我启动线程,然后使用ThrCountIncr
。
ThreadTest Thrtest = new ThreadTest();
Thread thr = new Thread(Thrtest);
thr.start();
Thrtest.ThrCountIncr();
线程检查ThrCount
变量值,如果它大于10,它将停止程序。没有sleep(100)
,线程不会停止程序,我认为它不会检查变量值。为什么调用sleep
会使此代码生效?
答案 0 :(得分:11)
即使使用Thread.sleep()
,它也可能不起作用。这是因为您没有正确地同步对共享ThrCount
变量的访问。
如果您创建该变量volatile
,则不应再看到任何问题。但是,由于++
操作不是原子操作,它可能不会完全循环10次。
理想情况下,您应该使用AtomicInteger并使用其incrementAndGet()
方法。
另请注意:
thrCount
,thrCountIncr()
sleep
是一种静态方法,因此您只需调用Thread.sleep(...);
即可在当前线程中休眠。答案 1 :(得分:4)
如果您的线程没有休眠,其他线程可能无法工作,因此ThrCountIncr
内的循环可能随时被卡住(可能在第一个sleep
或{ {1}})。
在没有任何睡眠或等待的情况下,永远不要让线程循环。
另请注意,如果您不使用同步保护它,println
可能会失败,因为它不是原子操作。
答案 2 :(得分:3)
当循环迭代次数超过10,000次时,它可以通过JIT进行优化。在第二个线程的情况下,线程的代码不会修改字段,因此JIT可以优化if
条件或确定它始终运行。
如果您创建字段volatile
,则会阻止JIT进行此类优化。