繁体   English   中英

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

[英]Does Thread.sleep() stops calling threads run method?

有人可以向我解释一下我错过了什么:当我调用Thread.sleep(1000)时,我想两个线程都应该在 1s 内执行,所以在那之后我为什么要让doSlice false 在 1s 内停止线程,为什么Thread.sleep()只是不会在 1 秒内阻止他们。 我的意思是在 1s 之后运行方法甚至不应该被调用来检查 while 条件:

public class ExecutionScheduling  extends Thread{
    public int slice_count=0;
    public boolean doSlice=true;
    public String name;

    public ExecutionScheduling(String name){
        this.name=name;
    }

    public void run() {
        while (doSlice) {
            slice_count++;
            System.out.println(name);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ExecutionScheduling executionScheduling=new ExecutionScheduling("ex");
        ExecutionScheduling executionScheduling1=new ExecutionScheduling("ex1");

        executionScheduling.start();
        executionScheduling1.start();

        Thread.sleep(1000);
        executionScheduling.doSlice=false;
        executionScheduling1.doSlice=false;

        System.out.println("ex: "+executionScheduling.slice_count);
        System.out.println("ex1: "+executionScheduling1.slice_count);
    }
}

有人可以向我解释我错过了什么

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

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

 Thread.sleep(1000);

当你运行这个 sleep 命令时,它会导致 go 的主线程休眠,但 2 个后台线程继续运行。 他们每个人都在更新自己的slice_count副本,但不能保证主线程会看到这些更新。

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

通过将volatile Java 关键字添加到slice_count ,这会将字段标记为被多个线程访问。 当主线程访问slice_count时,它将读取它的最新值。 您可能还想查看AtomicInteger ,它包装了一个volatile int但允许多个线程执行诸如incrementAndGet()之类的事情。

memory 同步问题的另一个地方是:

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 为您处理slice_count同步,因此只要您在join()调用完成访问它们,它们就不再需要是volatile的。 是的,这令人困惑。 线程编码是不平凡的。 您仍然需要doSlice字段是volatile的,因为它们是在join()完成之前访问的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM