2スレッドのFixedThreadPoolExecutorServiceにラップされたCompletionServiceを使用して、いくつかのFutureタスクを送信し、送信されたタスクの数に等しいループを設定してセットアップし、completionservice.take()を使用してすべてが完了するか失敗するのを待ちます。問題は非常にまれに終了しないことがあるので(理由はわかりません)、take()メソッドをpoll(300、Timeout.SECONDS)に変更しました。これは、1つのタスクが完了するまでに5分以上かかる場合のアイデアです。ポーリングは失敗し、最終的にはループから抜け出します。すべての先物を調べて、future.cancel(true)を呼び出して、問題のあるタスクを強制的にキャンセルできます。
しかし、コードを実行してハングすると、ポーリングが5分ごとに1回継続して失敗し、それ以上タスクが実行されないことがわかります。そのため、2人のワーカーが何らかの方法でデッドロックし、終了せず、追加のタスクの開始を許可しないと想定します。タイムアウトは5分であり、実行するタスクがまだ1000あるため、ループを解除するのにかかる時間が長すぎたため、ジョブをキャンセルしました。
ですから、私がやりたいのは、5分以内に完了しなかった場合に現在のタスクを中断/強制的にキャンセルすることですが、それを行う方法がわかりません。
このコードサンプルは、Imが話していることの簡略版を示しています
import com.jthink.jaikoz.exception.JaikozException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;
public class CompletionServiceTest
{
public static void main(final String[] args)
{
CompletionService<Boolean> cs = new ExecutorCompletionService<Boolean>(Executors.newFixedThreadPool(2));
Collection<Worker> tasks = new ArrayList<Worker>(10);
tasks.add(new Worker(1));
tasks.add(new Worker(2));
tasks.add(new Worker(3));
tasks.add(new Worker(4));
tasks.add(new Worker(5));
tasks.add(new Worker(6));
List<Future<Boolean>> futures = new ArrayList<Future<Boolean>>(tasks.size());
try
{
for (Callable task : tasks)
{
futures.add(cs.submit(task));
}
for (int t = 0; t < futures.size(); t++)
{
Future<Boolean> result = cs.poll(10, TimeUnit.SECONDS);
if(result==null)
{
System.out.println("Worker TimedOut:");
continue;
}
else
{
try
{
if(result.isDone() && result.get())
{
System.out.println("Worker Completed:");
}
else
{
System.out.println("Worker Failed");
}
}
catch (ExecutionException ee)
{
ee.printStackTrace();
}
}
}
}
catch (InterruptedException ie)
{
}
finally
{
//Cancel by interrupting any existing tasks currently running in Executor Service
for (Future<Boolean> f : futures)
{
f.cancel(true);
}
}
System.out.println("Done");
}
}
class Worker implements Callable<Boolean>
{
private int number;
public Worker(int number)
{
this.number=number;
}
public Boolean call()
{
if(number==3)
{
try
{
Thread.sleep(50000);
}
catch(InterruptedException tie)
{
}
}
return true;
}
}
出力
Worker Completed:
Worker Completed:
Worker Completed:
Worker Completed:
Worker Completed:
Worker TimedOut:
Done