[英]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.