簡體   English   中英

Future.get() 是 Thread.join() 的替代品嗎?

[英]Is Future.get() a replacement for Thread.join()?

我想編寫一個永遠運行的命令行守護程序。 我知道,如果我希望 JVM 能夠在 linux 中正常關閉,則需要通過一些 C 代碼包裝引導程序。 我想我現在可以使用關機鈎子了。

關於我的問題:

  1. 我的 main(String[]) 塊將觸發一個單獨的超級守護進程。
  2. 超級守護進程將永遠輪詢和循環。

所以通常我會這樣做:

class Superdaemon extends Thread { ... }

class Bootstrap
{
    public static void main( String[] args )
    {
        Thread t = new Superdaemon();
        t.start();

        t.join();
    }
}

現在我想如果我通過 Executor 啟動 Superdaemon,我可以做到

Future<?> f = exec.submit( new Superdaemon() );

f.get();

Future.get()是用 Thread.join() 實現的嗎? 如果不是,它的行為是否相同?

問候,

明孝

是的,你寫這些的方式是等價的。

但是,您實際上並不需要等待 Superdaemon 線程完成。 當主線程完成執行 main() 時,該線程退出,但 JVM 不會。 JVM 將繼續運行,直到最后一個非守護線程退出其運行方法。

例如,

public class KeepRunning {
  public static void main(String[] args) {
    Superdaemon d = new Superdaemon();
    d.start();
    System.out.println(Thread.currentThread().getName() + ": leaving main()");
  }
}

class Superdaemon extends Thread {
  public void run() {
    System.out.println(Thread.currentThread().getName() + ": starting");
    try { Thread.sleep(2000); } catch(InterruptedException e) {}
    System.out.println(Thread.currentThread().getName() + ": completing");
  }
}

您將看到 output:

main: leaving main()
Thread-0: starting
Thread-0: completing

換句話說,主線程首先完成,然后輔助線程完成,JVM 退出。

問題是像 JCIP 這樣的書提倡我們使用 Executors 來啟動 Threads。 所以我盡量不使用 Thread.start()。 我不確定我是否一定會僅僅基於簡單性而選擇一種特定的做事方式。 一定有一個更有說服力的理由,不是嗎?

使用java.util.concurrent令人信服的理由是多線程編程非常棘手。 Java 提供了相應的工具(線程,同步和易失性關鍵字),但這並不意味着您可以安全地直接使用它們而不會自欺欺人:要么同步太多,導致不必要的瓶頸和死鎖,要么太少,由於競爭條件導致行為不穩定)。

使用java.util.concurrent ,您可以獲得一組實用程序(由專家編寫),用於最常見的使用模式,您可以直接使用它們,而不必擔心您得到了正確的低級內容。

但是,在您的特定情況下,我完全不明白為什么您需要一個單獨的線程,您不妨使用主線程:

public static void main( String[] args )
{
    Runnable t = new Superdaemon();
    t.run();
}

執行器適用於您希望在后台運行的任務(當您有多個並行任務或當前線程可以繼續執行其他操作時)。

Future.get() 將從異步調用中獲得未來的響應。 如果調用尚未完成,這也會阻塞。 它很像線程連接。

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Future.html

排序。 Future.get()用於關閉線程 go 並計算一些東西,然后以安全的方式將其返回給調用線程。 如果get永遠不會返回,它會起作用。 但是,我會堅持使用join調用,因為它更簡單並且沒有 Executer 開銷(並不是說會有那么多)。

編輯

看起來ExecutorService.submit(Runnable)旨在完全按照您的嘗試進行。 它只是在Runnable完成時返回null 有趣的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM