2

我有以下代码:

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使此代码起作用?

4

3 回答 3

11

即使使用Thread.sleep()它也可能无法正常工作。这是因为您没有正确同步对共享ThrCount变量的访问。

如果您设置该变量volatile,您应该不会再看到任何问题。但是,由于++操作不是原子的,因此它可能不会精确循环 10 次。

理想情况下,您应该使用 AtomicInteger 并使用它的incrementAndGet()方法。

另请注意:

  • Java 命名约定:变量和方法名称应以小写 ( thrCount,thrCountIncr()
  • sleep是一个静态方法,所以你可以简单地调用Thread.sleep(...);它,它会在当前线程中休眠。
于 2012-11-13T16:44:52.640 回答
4

如果你的线程不休眠,其他线程可能无法工作,所以里面的循环ThrCountIncr随时都可能卡住(可能在第一个sleep或第一个println)。

永远不要让线程在没有任何睡眠或等待的情况下循环。

另请注意,ThrCount++;如果您不使用同步保护它可能会失败,因为它不是原子操作。

于 2012-11-13T16:44:33.483 回答
3

当循环迭代超过 10,000 次时,它可以通过 JIT 进行优化。在第二个线程的情况下,线程的代码不会修改该字段,因此 JIT 可以优化掉if条件或确定它始终运行。

如果您创建该字段,volatile这会阻止 JIT 进行此类优化。

于 2012-11-13T16:59:05.913 回答