質問

についてかなり単純な質問があります スレッドプールエグゼキュータ. 。次のような状況があります。キューからオブジェクトを消費し、それらに適切なワーカー タスクを作成して、ThreadPoolExecutor に送信する必要があります。これは非常に簡単です。ただし、シャットダウンシナリオ内では 多くの ワーカーは実行のキューに入れられる可能性があります。これらのタスクの 1 つは 1 時間実行される可能性があり、アプリケーションを比較的高速に正常にシャットダウンしたいので、すでに処理されているタスクが正常に完了する間に、キューに入れられたすべてのタスクを ThreadPoolExecutor から破棄したいと考えています。

ThreadPoolExecutor のドキュメントには、 取り除く() ただし、特定のタスクのみを削除できます。 パージ() すでにキャンセルされた将来のタスクに対してのみ機能します。私のアイデアは、キューに入れられたすべてのタスクを保持しているキューをクリアすることでした。ThreadPoolExecutor はこの内部キューへのアクセスを提供しますが、ドキュメントには次のように記載されています。

メソッドgetQueue()を使用すると、監視とデバッグを目的として、作業キューにアクセスできます。他の目的のためにこの方法を使用することは強く落胆しています。

したがって、このキューを取得してクリアすることはできません。また、ドキュメントのこのスニペットには次のように書かれています。

2つの提供された方法、削除(java.lang.runnable)とpurge()は、多数のキューに囲まれたタスクがキャンセルされたときにストレージ再生を支援するために利用できます。

どうやって?確かに、エグゼキューターに送信したすべてのタスクのリストを維持できます。シャットダウンの場合は、すべてのエントリを反復処理し、remove() メソッドを使用して ThreadPoolExecutor から削除します。しかし...これはメモリの無駄であり、このリストを維持するのは面倒です。(実行済みタスクの削除など)

ヒントや解決策をいただければ幸いです。

役に立ちましたか?

解決

あなたはExecutorServiceのをラップして考えがありますか?

を作成します。
CleanShutdownExecutorService implements Executor 

別のエグゼキュータに委譲すべてのコールでなく、独自のリストに先物を保持します。 CleanShutdownExecutorServiceは、その後、()を呼び出してシャットダウンcancelRemainingTasks()メソッドを持つことができ、そのリスト内のすべての先物に(false)をキャンセルを呼び出します。

他のヒント

私は長い間、実行中のスレッドを持つアプリ上で動作するために使用しました。私たちは、

、シャットダウン時にこれを行います
BlockingQueue<Runnable> queue = threadPool.getQueue();
List<Runnable> list = new ArrayList<Runnable>();
int tasks = queue.drainTo(list);

リストをファイルに保存されます。私たちはどんな仕事を失うことはありませんので、起動時に、リストはプールに戻って追加されます。

として ExecutorService.shutdown() 十分にやっていないし、 ExecutorService.shutdownNow() やりすぎているので、途中で何かを書き込む必要があると思います。送信したすべてのタスクを記憶し、呼び出し後(または呼び出し前)に手動で削除します。 shutdown().

この古い質問ですが、場合には、これは他の誰かに役立ちます:あなたはあなたがシャットダウンを(呼び出したとき)は、揮発性ブール値を設定し、その真偽値が実際に開始する前に設定されている場合は、各提出タスクが終了する可能性があります。これは純粋に完了し始めているタスクが可能になりますが、その実際の活動を開始するから、キューに入れられたタスクを防ぐことができます。

ボムの答えは正確に何をしたいです。 shutdownNow()の核兵器を使用して、すべてを停止し、のアプローチを切り開きます。これは、あなたが使用しているThreadPoolExecutorの実装をサブクラスの短い、あなたができる最善のことです。

あなたが試すことができallowCoreThreadTimeOut(true);

あなたはあなた自身のタスクキューを作成して、コンストラクタをThreadPoolExecutorするためにそれを渡すことができます:

int poolSize = 1; // number of threads
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>();
Executor executor = new ThreadPoolExecutor(poolSize, poolSize, 0L, TimeUnit.MILLISECONDS, queue);

あなたは、あなたのコードのどこかでキューをクリアすると、残りのタスクが実行されません。

queue.clear();

(ない本物の思考を通して、またはテスト)働くかもしれない狂気と汚れたソリューションをのみの場合には、いくつかのグローバル値はinterrupt()がshutdownNowの(でそれらに呼び出されたときにシャットダウンするように拒否設定されているあなたのWorkerTasksのinterrupt()を上書きするだろう)ます。

あなたがいないshutdownNow()使用できるようにするべきだと?

removeメソッドを使用して、各Runnableをを削除し、個々のランナブルへのfor-eachの結果、シャットダウンにgetQueueをごスレッドプールを知らせます。キューのタイプに応じて、早期の戻り値に基づいて削除しを停止することができるかもしれません。

基本的に、これはのみ動作方法を経由してクリアし、キューをつかみ、それをクリアしています。代わりに、手動ですべての投稿を覚えるのは、スレッドプールは、すでにすべての提出を覚えなければならないという事実を使用しています。私はそれがライブビューですので、あなたが-eachingライブビュー上/反復処理された場合は、おそらく同時変更例外を引き起こす取り除くと思いますしかし、あなたはおそらく、キューの防御的なコピーを作成する必要があります。

シャットダウン後の作業をawaitTermination(long timeout, TimeUnit unit)ませんか?

executor.shutdown(); executor.awaitTermination(60、TimeUnit.SECONDS)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top