Thread.sleep()是否停止调用线程运行方法?

时间:2020-07-23 12:20:14

标签: java multithreading execution thread-sleep

有人可以向我解释一下我所缺少的吗:当我调用<CONTYPE>2</CONTYPE>时,我认为两个线程都应该在1s内执行,所以之后为什么我应该将Thread.sleep(1000)设置为false以在1s内停止线程 为什么doSlice不会在一秒钟内阻止他们。我的意思是1s之后的run方法甚至不应该在条件检查时调用:

Thread.sleep()

1 个答案:

答案 0 :(得分:3)

有人可以向我解释我所缺少的吗

您缺少的是线程之间的memory synchronization。当您启动2个后台线程时,它们具有自己的本地内存(在自己的CPU上),您需要专门更新它们之间的所有共享数据。

使代码复杂化的是,System.out.println(...)是一种同步方法,因此它“免费”为您提供了一些内存同步,但是您不应依赖它(请参见下文)。这意味着,如果删除该调试代码,则程序的行为将有所不同。小心在线程代码中使用System.out.print*

Thread.sleep(1000);

运行此sleep命令时,它将使主线程进入睡眠状态,但2个后台线程继续运行。他们每个人都在更新自己的slice_count副本,但不能保证主线程会看到这些更新。

// need to add the volatile keyword here
private volatile int slice_count;

通过将volatile Java keyword添加到slice_count,这会将字段标记为被多个线程访问。当主线程访问slice_count时,它将读取它的最新值。您可能还想研究AtomicInteger,它包装了volatile int,但允许多个线程执行类似incrementAndGet()的操作。

存在内存同步问题的另一个地方是:

executionScheduling.doSlice = false;
executionScheduling1.doSlice = false;

因此,doSlice字段也需要为volatile

// need to add the volatile keyword here
public volatile boolean doSlice = true;

最后,没有顺序:

  • 您的字段应尽可能为private

  • 应为executionScheduling1executionScheduling2

  • 定义Runnable而不是Thread是更好的模式。参见:https://stackoverflow.com/a/541527/179850

  • 您可能考虑在打印输出结果之前,先进行join()等待或每个线程完成其工作。

    // set the doSlices to false
    executionScheduling.join()
    executionScheduling1.join()
    // printf results
    

    如果您添加join()调用,那么它将以slice_count的名义为您处理内存同步,因此只要您访问它们,它们就不再需要volatilejoin()调用结束之后>。是的,这令人困惑。线程编码是不平凡的。您仍然需要将doSlice字段设置为volatile,因为它们是在{em> join()完成之前被访问的。