[英]Delay in the Finally block after try block completion
我試圖運行以下並發代碼:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class TestThread {
public static void main(final String[] arguments) throws
InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
executor.submit(new Task());
System.out.println("Shutdown executor");
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
System.err.println("tasks interrupted");
} finally {
if (!executor.isTerminated()) {
System.err.println("cancel non-finished tasks");
}
executor.shutdownNow();
System.out.println("shutdown finished");
}
}
static class Task implements Runnable {
public void run() {
try {
int duration = 6;
System.out.println("Running Task!");
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
輸出是:
Shutdown executor
Running Task!
shutdown finished
cancel non-finished tasks
java.lang.InterruptedException: sleep interrupted
根據輸出,似乎最后跳過塊,並且首先執行finally塊之后的代碼,然后執行finally塊。 這是否與在try / catch塊完成后最終執行的代碼的正常流程相矛盾?
編輯:試過
System.out.flush();
System.err.flush();
按照其中一個建議進行每次打印但仍然輸出相同。
編輯:
我正在使用在線編譯器。
我想你會期望這兩條跟蹤被反轉,因為它們是以相反的順序聲明的:
關機完了
取消未完成的任務
我認為問題來自於System.err
和System.out
的混合。
這些不是相同的流。 因此,他們的沖洗和顯示都可以在不同的時間進行。
根據顯示輸出的應用程序/系統(IDE,OS命令行,在線編譯器/執行程序),至少有兩件事可能會產生排序問題:
根據時間線顯示輸出的解決方法:
每次print()
調用后刷新流( System.out.flush()
和System.err.flush()
)。
它可能有效,但不能保證,因為寫入輸出的應用程序/系統可能無法通過時間線同步這兩個流的顯示。
努力只使用System.out
並僅在程序退出的錯誤情況下使用System.err
。 它將減少交錯的可能性。
如果最后一個想法不合適,因為清楚地區分這兩種輸出很重要,使用一個日志庫(Logback或Log4j2,最好是在外觀中使用SLF4J),它允許精確地跟蹤信息(日期,時間,嚴重性級別,...... 。)並按程序流程時間軸的實際順序讀取它們。
這是僅使用System.out
的相同代碼:
我添加了//1
, //2
,...注釋輸出的預期順序。
public class TestThread {
public static void main(final String[] arguments) throws InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
executor.submit(new Task());
System.out.println("Shutdown executor"); // 1
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
System.out.println("tasks interrupted"); // not invoked because caught in Task.run()
} finally {
if (!executor.isTerminated()) {
System.out.println("cancel non-finished tasks"); // 3
}
executor.shutdownNow();
System.out.println("shutdown finished"); // 4
}
}
static class Task implements Runnable {
public void run() {
try {
int duration = 6;
System.out.println("Running Task!"); // 2
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
輸出現在正如預期的那樣,無論程序運行在哪里都應該是相同的:命令行,IDE,...
關機執行人
跑步任務!
取消未完成的任務
關機完了
java.lang.InterruptedException:睡眠中斷
注意 :
java.lang.InterruptedException:睡眠中斷
可能仍然在順序上有所不同,因為Throwable.printStackTrace()
依賴於system.err
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.