public class MainClass {
private static final int size = 5;
private ExecutorService prodExec = Executors.newFixedThreadPool(size);
private ExecutorService consExec = Executors.newFixedThreadPool(size);
//main method here
public void start(String[] args) {
for (int index = 0; index < size; index++) {
Runnable producer = new Producer(consExec, listOfIds);
prodExec.execute(producer);
}
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
prodExec.shutdown();
try {
prodExec.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ignore) {
}
consExec.shutdown();
try {
consExec.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ignore) {
}
}
});
}
}
public class Producer implements Runnable {
private ExecutorService consExec;
private List<Long> list;
public Producer(ExecutorService exec, List<Long> list) {
this.consExec = exec;
this.list = list;
}
public void run() {
for (Long id: list) {
data = get data from db for the id
consExec.execute(new Consumer(data));
}
}
}
public class Consumer implements Runnable {
public void run() {
// call web service
}
}
ユーザーがシャットダウンを要求したときに、Ctrl + Cキーを押してシナリオを処理したいと考えています。私はこれがシャットダウンフックで実行できると思います。しかし、上記のコードのように、各プロデューサは、処理するIDのリスト(250かもしれません)を取得します。つまり、dbを呼び出してIDのデータを取得し、データをコンシューマスレッドに送信します。サービス。プロデューサーのコンシューマーリクエストの取り消し
プロデューサスレッドのそれぞれのforループから、シャットダウンが要求されたときに各スレッドがまだプロセスされていないIDを処理しないようにするにはどうすればよいですか? shutDownHookを動作させることができましたが、シャットダウン要求の場合にrun()メソッドを終了するためにrunメソッド内のロジックを各スレッドに組み込む方法を確認できませんでした。ブール変数(AtomicBoolean)を外部的に設定すると、各スレッドがすべてのIDを処理する前にforループをチェックインすることがありますか?
私が理解しているように、shutdown()を呼び出すと、送信されたすべてのタスクが実行されて終了します。この場合、タスクはすでにexecutorサービス上でキューに入れられているため、処理を停止する方法はありません。
shutdown()の代わりにshutdownNow()を呼び出すと、予期しない結果が生じることがありますか?
ifブロックにsysout( "中断")ステートメントを追加しようとしましたが、提案したようにshutdownNow()を実行しようとしましたが、スレッドによってはステートメントが印刷されませんでした。たとえば、1000個のスレッドを生成し、それぞれに一意の名前を割り当て、shutDownHook()でshutdownNow()を呼び出し、Ctrl + Cを押しました。中断されたステートメントは、いくつかのスレッド、すなわちrun()を終了したスレッドの総数と中断されたスレッドの数が、実行されたスレッドの総数に加算されません。私は、interruptNow()のスレッドでinterrupt()が呼び出されると確信できますか? – Oxford
これはおそらく、あなたが作成した1000スレッドのうちのほんの数だけが実際に何らかの作業をしていたためです。あれは正しいですか?その場合、残りの部分はBlockingQueueを待っています。この時点での中断は、ExecutorServiceによって処理されます。簡単な答えは、他のM個のスレッド(実際に実行されている1000〜N個のタスクであるM個のスレッド)が 'public void run()'メソッドになかったからです。 –
そして、ExecutorServiceによって処理されると、 ExecutorServiceは残りのスレッドを適切にシャットダウンします。 –