2017-11-02 15 views
0

私はExecutorServiceを持っており、タイムアウトを設定しました。次に、invokeAll()メソッドを使用してスレッドの実行を開始します。ExecutorServiceでキャンセルされたタスクを確認するには?

List<Callable<Portlet>> taskList = new ArrayList(); 

for (int i = 0; i < rules.size(); i++) { 
    Rule rule = rules.get(i); 
    Callable<Portlet> worker = new RuleExecuterThread(rule); 
    taskList.add(worker); 
} 


List<Future<Portlet>> invokedList = null 

try { 
    invokedList = springThreadPoolTaskExecutor.getThreadPoolExecutor().invokeAll(taskList, 1200, TimeUnit.MILLISECONDS); 
} catch (InterruptedException e) { 
    LOGGER.error(e.getMessage(), e); 
    invokedList = new ArrayList<>(); 
} 

List<Portlet> collectedList = new ArrayList<>(); 

for(Future<Portlet> t : invokedList) { 
    try { 
     collectedList.add(t.get()); 
    } catch (CancellationException e) { 
     LOGGER.error(e.getMessage(), e); 
    } 
} 

取り消されたタスクは、CancellationException catchブロックで処理されます。私がしたいのは、キャンセルされたタスクオブジェクト(ルールオブジェクト)のインスタンスで、どのタスクがキャンセルされたかを確認したいのです。しかし、将来のオブジェクトにはそれに関する情報は含まれていません。

この情報はどのように入手できますか?

ありがとうございました。

答えて

0

私はこれを回避する方法を書いたが、これを行うには優雅な方法はないと思う。基本的に私はThreadPoolExecutorとFutureとCallableを拡張し、オブジェクトを取得するために型キャストを行った。

ここにコードがあります。その小さなハッキーが動作します。

interface Portlet { } 

static class Rule { 

    private final int id; 

    private Rule(int id) { 
     this.id = id; 
    } 

    @Override 
    public String toString() { 
     return "Rule{" + 
       "id=" + id + 
       '}'; 
    } 
} 

static class Pool extends ThreadPoolExecutor { 

    private Pool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { 
     super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); 
    } 

    @Override 
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { 
     return new InterestingFuture<>(callable); //Create a different type of future with which you can get your callable. 
    } 
} 

static class RuleExecuterThread implements Callable<Portlet> { 

    private final Rule rule; 

    private RuleExecuterThread(Rule rule) { 
     this.rule = rule; 
    } 

    @Override 
    public Portlet call() throws Exception { 
     Thread.sleep(2000);//Simulate wait. 
     return new Portlet() { 
     }; 
    } 
} 

static class InterestingFuture<T> extends FutureTask<T> { 

    private final Callable<T> callable; 

    private InterestingFuture(Callable<T> callable) { 
     super(callable); 
     this.callable = callable; 
    } 

    private Callable<T> getCallable() { 
     return callable; 
    } 
} 

void printCancelTask() throws InterruptedException { 
    List<Callable<Portlet>> taskList = new ArrayList<>(); 

    for (int i = 0; i < 10; i++) { 
     Callable<Portlet> worker = new RuleExecuterThread(new Rule(i)); 
     taskList.add(worker); 
    } 

    ExecutorService executorService = new Pool(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); 
    List<Future<Portlet>> futures = executorService.invokeAll(taskList, 10000, TimeUnit.MILLISECONDS); 

    for (Future<Portlet> taskFuture : futures) { 
     if(taskFuture.isCancelled()) { //Task got cancelled due to timeout. 
      InterestingFuture future = (InterestingFuture) taskFuture; //Type cast here. 
      RuleExecuterThread t = (RuleExecuterThread) future.getCallable(); //Type cast it again 

      System.out.println(t.rule); //You cancelled rule. 
     } 
    } 
} 

明らかにあなたはプールが必要に応じて曲をすることができますし、多分それでエグゼキュータをラップ(使用しているクラスの名前を使用しようとしました)。私の解決策は、それを解決する1つの方法を提供します。

関連する問題