Thread.sleep() 是否停止调用线程 运行 方法?
Does Thread.sleep() stops calling threads run method?
有人可以向我解释我遗漏了什么吗:当我调用 Thread.sleep(1000)
时,我想两个线程都应该在 1s 内执行,所以在那之后为什么我应该让 doSlice
false 停止线程1秒
为什么 Thread.sleep()
不能在 1 秒内阻止他们。我的意思是在 1s 运行 方法之后甚至不应该调用来检查 while condition:
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);
}
}
Can someone please explain to me what I am missing
您缺少的是线程之间的 memory synchronization。当您启动 2 个后台线程时,它们有自己的本地内存(在它们自己的 CPU 上),您需要专门更新它们之间的任何共享数据。
使代码复杂化的是 System.out.println(...)
是一种同步方法,因此它“免费”为您提供了一些内存同步,但您不应该依赖它(见下文)。这意味着如果您删除了该调试代码,您的程序将表现不同。请注意线程代码中 System.out.print*
的任何用法。
Thread.sleep(1000);
当你运行这个睡眠命令时,它会导致主线程进入睡眠状态,但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
。
应该是executionScheduling1
和executionScheduling2
.
定义 Runnable
比 Thread
更好。参见:
您可以考虑做一个 join()
等待或每个线程完成它们的工作,然后再打印出它们的结果。
// set the doSlices to false
executionScheduling.join()
executionScheduling1.join()
// printf results
如果您添加 join()
调用,那么这将根据 slice_count
为您处理内存同步,因此只要您访问它们就不再需要 volatile
在 join()
调用完成后。是的,这令人困惑。线程编码非常重要。您仍然需要 doSlice
字段为 volatile
,因为它们在 在 join()
完成之前被访问。
有人可以向我解释我遗漏了什么吗:当我调用 Thread.sleep(1000)
时,我想两个线程都应该在 1s 内执行,所以在那之后为什么我应该让 doSlice
false 停止线程1秒
为什么 Thread.sleep()
不能在 1 秒内阻止他们。我的意思是在 1s 运行 方法之后甚至不应该调用来检查 while condition:
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);
}
}
Can someone please explain to me what I am missing
您缺少的是线程之间的 memory synchronization。当您启动 2 个后台线程时,它们有自己的本地内存(在它们自己的 CPU 上),您需要专门更新它们之间的任何共享数据。
使代码复杂化的是 System.out.println(...)
是一种同步方法,因此它“免费”为您提供了一些内存同步,但您不应该依赖它(见下文)。这意味着如果您删除了该调试代码,您的程序将表现不同。请注意线程代码中 System.out.print*
的任何用法。
Thread.sleep(1000);
当你运行这个睡眠命令时,它会导致主线程进入睡眠状态,但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
。应该是
executionScheduling1
和executionScheduling2
.定义
Runnable
比Thread
更好。参见:您可以考虑做一个
join()
等待或每个线程完成它们的工作,然后再打印出它们的结果。// set the doSlices to false executionScheduling.join() executionScheduling1.join() // printf results
如果您添加
join()
调用,那么这将根据slice_count
为您处理内存同步,因此只要您访问它们就不再需要volatile
在join()
调用完成后。是的,这令人困惑。线程编码非常重要。您仍然需要doSlice
字段为volatile
,因为它们在 在join()
完成之前被访问。