問題タブ [executorservice]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - これには同期が必要ですか?
以下のクラスでは、singleThreadScheduledExecutor を使用しています。私の質問は、dummyInt と dummyBoolean へのアクセスを同期する必要がありますか?
java - TimeoutExceptionが発生してもJVMは終了しません
私はこのようなことをする必要があるコードを持っています
それぞれにいくつかのメソッド(execute()など)を持つクラスのリストがあります。各クラスでそのメソッドを呼び出す必要があり、呼び出しごとに固定のtimeOutがあります。現在、クラスのexecuteメソッドの1つが正しく記述されておらず、jvmが終了しないためにタイムアウトが発生します。私はこのようにクラスを運営しています。
コードの実行が完了した後、jvmが終了しないのはなぜですか?
次の出力が得られます
2番目のクラスの実行がタイムアウトし、その後、3番目のクラスの実行もタイムアウトします。3番目のクラスの実行がタイムアウトするのはなぜですか?
実行が完了した後、jvmは終了しません。理由は何ですか?また、TestClass3
実行がタイムアウトするのはなぜですか?
java - 例外からの出力なし
このコードが例外スタックトレースを出力しないのはなぜですか?
どうすれば入手できますか?
私はこれを見ることを期待します:
java - java.util.concurrent.Future.get()が返されない
私は次のJavaコードを持っています:
exeService
のインスタンスはどこですか
問題は、myObject.doSomething()
二度と戻らないことです。したがって、future.get()
二度と戻らないということです。
submit
ただし、への呼び出しを次のような呼び出しに置き換えると、execute
次のようになります。
の呼び出しmyObject.doSomething()
は戻ります。それが重要かどうかはわかりませんdoSomething()
が、void
方法です。
使用時に終了するのに、使用しないときにdoSomething()
終了するのはなぜですか?execute
submit
また、使用する必要はありませんFuture.get()
; それがこれを行う最も自然な方法のように思えました。(私も同じ問題に遭遇しCountdownLatch
ます。)要点は、先に進む前に終了するのを待つ必要があるということです。doSomething()
複雑な理由から、ここでは説明しません。別のスレッドで起動する必要があります。これを行う別の方法が機能する場合は、それで問題ありません。
java - ExecutorServiceキュー内の各Runnableタイプの1つを制限する
いくつかの異なるタスクを送信するExecutors.newFixedThreadPool(1)があり(すべてRunnableを実装しています)、それらはキューに入れられ、順番に正しく実行されますか?各タスクの1つだけを一度に実行またはキューに入れることを許可する最良の方法は何ですか?すでにキューにあるExecutorServiceに送信されたすべてのタスクを無視したいと思います。
java - Future.get()はどのような場合にExecutionExceptionまたはInterruptedExceptionをスローしますか
私のコードスニペット:
InterruptedException
コード内でとをどのように処理する必要がExecutionException
ありますか?
そして、どのような場合に、これらの例外がスローされますか?
java - Java で最も高速な周期的同期は何ですか (ExecutorService と CyclicBarrier と X)?
以下に概説するような固定数のスレッドを使用した同時反復処理シナリオで最高のパフォーマンスを提供する可能性が高い Java 同期構造はどれですか? しばらく自分で (ExecutorService と CyclicBarrier を使用して) 実験し、その結果に少し驚いた後、専門家のアドバイスや新しいアイデアをいただければ幸いです。ここでの既存の質問は、主にパフォーマンスに焦点を当てているようには見えないため、この新しい質問です。前もって感謝します!
アプリのコアは単純な反復データ処理アルゴリズムで、OS X 10.6 と Java 1.6.0_07 を実行している Mac Pro の 8 つのコアに計算負荷を分散するために並列化されています。処理されるデータは 8 つのブロックに分割され、各ブロックは Runnable に送られ、固定数のスレッドの 1 つによって実行されます。アルゴリズムの並列化はかなり簡単で、機能的には期待どおりに機能しますが、そのパフォーマンスはまだ私が考えているほどではありません. アプリはシステム コールの同期に多くの時間を費やしているようです。そのため、いくつかのプロファイリングの後、最も適切な同期メカニズムを選択したかどうか疑問に思います。
アルゴリズムの重要な要件は、段階的に進行する必要があるため、各段階の最後にスレッドを同期する必要があることです。メインスレッドは作業を準備し (非常に低いオーバーヘッド)、それをスレッドに渡し、作業をさせ、すべてのスレッドが完了すると処理を進め、作業を再配置し (これも非常に低いオーバーヘッド)、サイクルを繰り返します。マシンはこのタスク専用であり、事前に割り当てられた項目のスレッドごとのプールを使用することでガベージ コレクションが最小限に抑えられ、スレッドの数を固定できます (着信要求などはなく、CPU コアごとに 1 つのスレッドのみ)。
V1 - ExecutorService
私の最初の実装では、8 つのワーカー スレッドを持つ ExecutorService を使用しました。プログラムは、作業を保持する 8 つのタスクを作成し、大まかに次のように作業させます。
これは機能的にはうまく機能し (本来あるべきことを行います)、実際、非常に大きな作業項目の場合、処理アルゴリズムが許容できる限り、8 つの CPU すべてに高い負荷がかかります (一部の作業項目は他の作業項目よりも速く終了し、その後アイドル状態になります)。 . ただし、作業項目が小さくなると (これは実際にはプログラムの制御下にはありません)、ユーザーの CPU 負荷は劇的に減少します。
凡例: - ブロック サイズ = ワークアイテムのサイズ (= 計算ステップ) - システム = OS X アクティビティ モニター (赤いバー) で示されるシステム負荷 - ユーザー = OS X アクティビティ モニター (緑のバー) で示されるユーザー負荷- サイクル/秒 = メインの while ループの繰り返し、多いほど良い
ここで主に懸念されるのは、システムで費やされる時間の割合が高いことです。これは、スレッド同期呼び出しによって引き起こされているようです。予想どおり、小さい作業項目の場合、ExecutorService.invokeAll() は、各スレッドで実行される作業の量に対して、スレッドを同期するためにより多くの労力を必要とします。しかし、ExecutorService は、このユース ケースで必要とされるよりも一般的であるため (コアよりも多くのタスクがある場合、スレッドのタスクをキューに入れることができます)、より無駄のない同期構造が存在する可能性があります。
V2 - CyclicBarrier
次の実装では、大まかに次のように、CyclicBarrier を使用して、作業を受け取る前と完了した後にスレッドを同期させました。
繰り返しますが、これは機能的にはうまく機能し (本来あるべきことを行います)、非常に大きな作業項目の場合、以前と同様に 8 つの CPU すべてに高い負荷がかかります。ただし、作業項目が小さくなると、負荷は依然として劇的に縮小します。
大規模な作業項目の場合、同期は無視でき、パフォーマンスは V1 と同じです。しかし予想外に、(高度に専門化された) CyclicBarrier の結果は、(一般的な) ExecutorService の結果よりもはるかに悪いように見えます: スループット (サイクル/秒) は V1 の約 1/4 にすぎません。これは CyclicBarrier の宣伝されている理想的な使用例のように見えますが、一般的な ExecutorService よりもパフォーマンスがはるかに悪いというのが暫定的な結論です。
V3 - 待機/通知 + CyclicBarrier
最初の循環バリア await() を単純な待機/通知メカニズムに置き換えてみる価値があるように思われました。
繰り返しますが、これは機能的にうまく機能します (本来あるべきことを行います)。
小さな作業項目のスループットは、ExecutorService よりもはるかに劣りますが、CyclicBarrier の約 2 倍です。CyclicBarrier を 1 つ削除すると、ギャップの半分が削除されます。
V4 - 待機/通知の代わりにビジー待機
このアプリはシステム上で実行されている主要なアプリであり、コアが作業項目でビジーでない場合はとにかくアイドル状態であるため、CPU を不必要に回転させても、各スレッドで作業項目をビジー状態で待機してみませんか。ワーカー スレッド コードは次のように変更されます。
また、機能的にもうまく機能します(本来あるべきことを行います)。
小さな作業項目の場合、これにより、CyclicBarrier + 待機/通知バリアントよりもスループットがさらに 10% 向上しますが、これは重要ではありません。ただし、ExecutorService を使用した場合でも、V1 よりもはるかにスループットが低くなります。
V5 - ?
では、そのような (おそらく珍しいことではない) 問題に最適な同期メカニズムは何でしょうか? ExecutorService を完全に置き換える独自の同期メカニズムを作成するのにうんざりしています (それがあまりにも一般的であり、より効率的にするためにまだ取り出すことができるものが必要であると仮定します)。それは私の専門分野ではなく、不確実な利益のためにデバッグに多くの時間を費やすことになるのではないかと心配しています(待機/通知およびビジー待機バリアントが正しいかどうかさえわからないため)。
アドバイスをいただければ幸いです。
java - タイムアウト後にタスクを中断する ExecutorService
タイムアウトを提供できるExecutorService実装を探しています。ExecutorService に送信されたタスクは、実行にタイムアウトよりも時間がかかる場合、中断されます。このような野獣を実装するのはそれほど難しい作業ではありませんが、既存の実装について知っている人がいるかどうか疑問に思っています。
以下の議論のいくつかに基づいて私が思いついたものは次のとおりです。コメントはありますか?
java - 新しい種類のスレッドが実行される場合、より大きなスレッドプールまたは追加の ExecutorService ですか?
ExecutorService
Java での s のオーバーヘッドの可能性に関連する質問があります。
現在の実装ExecutorService A
では、5 つのスレッドの容量があります。
- タイプのスレッドを実行し
A
ます。 - タイプ
A
スレッドは、データベースの読み取りと書き込みを行います。
これで、 type のスレッドは、 type のいくつかのスレッドが終了B
した後に実行されます。A
- 実行されるタイプ
B
スレッドの数は、その時々で異なります。 - タイプ
B
スレッドは、(データベースではなく) ファイルシステム IO を実行します。
だから私はすべきですか
ExecutorService
タイプのB
スレッドを処理するために新しいものを追加します- または、その容量を増やして
ExecutorService A
タイプB
スレッドを実行する必要がありますか?
Java が を 2 つ持つために余分なオーバーヘッドが発生する可能性があると考えていますがExecutorService
、その一方でスレッドの総数はいずれにせよ増加します。それはまったく問題ですか?
java - Java 同時実行 API を使用して動的データフローをモデル化する手法
EDIT:これは基本的に「Javaでデータフローエンジンを適切に実装する方法」の質問であり、これは単一の回答では適切に答えられないと感じています(「ORMレイヤーを適切に実装する方法」を尋ねて、誰かにHibernate などの詳細を書き出してください)、この質問は「閉じた」と考えてください。
Javaで動的データフローをモデル化するエレガントな方法はありますか? データフローとは、さまざまな種類のタスクが存在することを意味し、これらのタスクは任意に「接続」できます。たとえば、タスクが終了すると、終了したタスクの出力を入力として後続のタスクが並列に実行されたり、複数のタスクが終了したときにそれらのタスクが実行されたりします。出力は後続タスクに集約されます (フローベースのプログラミングを参照)。動的とは、タスクが終了したときの後続タスクのタイプと数が、その終了したタスクの出力に依存することを意味します。たとえば、タスク A は、特定の出力がある場合はタスク B を生成する可能性がありますが、ある出力がある場合はタスク C を生成する可能性があります。別の出力。別の言い方をすれば、各タスク (または一連のタスク) が次のタスクを決定する責任があるということです。
Web ページをレンダリングするためのサンプル データフロー: タスクの種類として、ファイル ダウンローダー、HTML/CSS レンダラー、HTML パーサー/DOM ビルダー、画像レンダラー、JavaScript パーサー、JavaScript インタープリターがあります。
- HTML ファイルのファイル ダウンローダ タスク
- HTML パーサー/DOM ビルダー タスク
- 各埋め込みファイル/リンクのファイル ダウンローダ タスク
- 画像の場合、画像レンダラー
- 外部 JavaScript の場合、JavaScript パーサー
- JavaScript インタープリター
- それ以外の場合は、HTML パーサー タスクの一部の var/field に格納するだけです
- 各埋め込みスクリプトの JavaScript パーサー
- JavaScript インタープリター
- 上記のタスクが完了するのを待ってから、HTML/CSS レンダラー (明らかに最適または完全に正しいわけではありませんが、これは簡単です)
- 各埋め込みファイル/リンクのファイル ダウンローダ タスク
- HTML パーサー/DOM ビルダー タスク
私は、ソリューションが何らかの包括的なフレームワークである必要があると言っているわけではありません (実際、JDK API に近いほど良いです)。重量級のものは、Spring Web Flow や宣言型マークアップ、その他の DSL などとはまったく異なります。 .
より具体的に言うと、Callables、Executors、ExecutorCompletionServices、およびおそらくさまざまなシンクロナイザー クラス (Semaphore や CountDownLatch など) を使用して Java でこれをモデル化する良い方法を考えようとしています。いくつかの使用例と要件があります。
- タスクが実行されるエグゼキューターについて、仮定をしないでください。実際、簡単にするために、エグゼキュータが 1 つしかないと仮定します。これは固定スレッド プールのエグゼキュータである可能性があるため、単純な実装ではデッドロックが発生する可能性があります (たとえば、別のタスクをサブミットし、そのサブタスクが完了するまでブロックするタスクを想像してください。これらのタスクのいくつかがすべてのスレッドを使い果たしていると想像してください)。
- 簡単にするために、データがタスク間でストリーミングされないと仮定します (タスク出力 -> 後続タスク入力)。終了タスクと後続タスクは一緒に存在する必要がないため、後続タスクへの入力データは、前のタスク (既に完了しているため)。
- データフロー「エンジン」が処理できる操作は、次の 2 つだけです。
- タスクがより多くのタスクをキューに入れることができるメカニズム
- 必要なすべての入力タスクが完了するまで、後続タスクがキューに入れられないメカニズム
- フローが終了するまでメイン スレッド (またはエグゼキュータによって管理されていない他のスレッド) がブロックされるメカニズム
- 特定のタスクが完了するまでメイン スレッド (またはエグゼキュータによって管理されていない他のスレッド) がブロックされるメカニズム
- データフローは動的 (タスクの入力/状態に依存) であるため、これらのメカニズムのアクティブ化はタスク コード内で発生する必要があります。
- データフローの「内部」は、タスク (Callable) 自体に公開しないでください。上記の操作のみをタスクで使用できるようにする必要があります。
- データのタイプは、すべてのタスクで必ずしも同じではないことに注意してください。たとえば、ファイル ダウンロード タスクは、入力としてファイルを受け入れますが、文字列を出力します。
- タスクがキャッチされていない例外 (すべてのデータフロー処理を停止する必要がある致命的なエラーを示す) をスローした場合、できるだけ早くデータフローを開始したスレッドまで伝播し、すべてのタスク (または致命的なエラー ハンドラーのようなより手の込んだもの) をキャンセルする必要があります。
- タスクはできるだけ早く開始する必要があります。これは、前の要件とともに、単純な Future ポーリング + Thread.sleep() を排除する必要があります。
- おまけとして、タスクが終了するたびに、または最後のタスクが終了してから X 時間が経過したときに、データフロー エンジン自体に何らかのアクション (ログ記録など) を実行させたいと考えています。何かのようなもの:
ExecutorCompletionService<T> ecs; while (hasTasks()) { Future<T> future = ecs.poll(1 minute); some_action_like_logging(); if (future != null) { future.get() ... } ... }
Java 同時実行 API を使用してこれらすべてを行う簡単な方法はありますか? または、JDK で使用できるものを使用しても複雑になる場合、要件を満たす軽量のライブラリはありますか? 私はすでに、私の特定のユース ケースに適合する部分的なソリューションを持っています (私は 2 つのエグゼキューターを使用しているため、ある意味でごまかしています。ご存じのとおり、上記の Web ブラウザーの例とはまったく関係ありません)。より汎用的で洗練されたソリューションを見たいと思っています。