[英]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
的。
它应该是executionScheduling1
和executionScheduling2
。
定义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.