Future.get()はThread.join()の代わりですか?
-
03-07-2019 - |
質問
永久に実行するコマンドラインデーモンを書きたいです。 LinuxでJVMを正常にシャットダウンできるようにするには、Cコードを介してブートストラップをラップする必要があることを理解しています。私は今のところシャットダウンフックで大丈夫だと思う。
質問について:
- 私のmain(String [])ブロックは、別のスーパーデーモンを起動します。
- スーパーデーモンは永久にポーリングしてループします。
したがって、通常は次のようにします。
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()で実装されていますか?
そうでない場合、同等に動作しますか?
よろしく、
ashitaka
解決
はい、これらの記述方法は同等です。
ただし、Superdaemonスレッドが完了するのを待つ必要はありません。メインスレッドがmain()の実行を終了すると、そのスレッドは終了しますが、JVMは終了しません。 JVMは、最後の非デーモンスレッドがrunメソッドを終了するまで実行を続けます。
たとえば、
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");
}
}
出力が表示されます:
main: leaving main()
Thread-0: starting
Thread-0: completing
つまり、メインスレッドが最初に終了し、次にセカンダリスレッドが完了してJVMが終了します。
他のヒント
問題は、JCIPのような本が、スレッドを開始するためにExecutorsを使用することを主張していることです。そのため、Thread.start()を使用しないように最善を尽くしています。単純さだけに基づいて特定の方法を選択する必要があるかどうかはわかりません。もっと説得力のある理由があるに違いない?
java.util.concurrent を使用する説得力のある理由は、マルチスレッドプログラミングが非常に難しいことです。 Javaはそのためのツール(スレッド、 synchronized および volatile キーワード)を提供しますが、それはあなたが足を撃たずに安全に直接使用できるという意味ではありません:どちらか同期が多すぎると、不必要なボトルネックとデッドロックが発生します。または、少なすぎると、競合状態による不安定な動作になります。
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()
は、スレッドをオフにして何かを計算し、安全な方法で呼び出し元のスレッドに返すためのものです。 get
が返されなかった場合は機能します。しかし、私は join
呼び出しに固執します。それはより単純で、Executerのオーバーヘッドがないためです(それほど多くはありません)。
編集
ExecutorService.submit(Runnable)
は、試みていることを正確に実行することを目的としています。 Runnable
が完了すると、単に null
を返します。興味深い。