2017-11-02 36 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 블록에서 처리됩니다. 내가 원하는 것은 취소 된 작업 객체를 얻으려는 것입니다.이 객체는 어떤 작업이 취소되었는지 확인하기 위해 규칙 객체입니다. 그러나 Future 객체에는 그것에 대한 정보가 포함되어 있지 않습니다.

어떻게 정보를 얻을 수 있습니까?

감사합니다.

답변

0

나는이 방법을 사용하여 우아한 방법이 있다고 생각하지 않습니다. 기본적으로 나는 ThreadPoolExecutor뿐만 아니라 Future and Callables를 확장하고 객체를 검색하기 위해 일부 유형 변환을 수행했습니다.

다음은 코드입니다. 그 작은 해키하지만 작동합니다. 분명히 당신은 조정 필요에 어쩌면 따라 수영장가에 Executor에 포장 할 수

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. 
     } 
    } 
} 

(사용하는 클래스의 이름을 사용하려고). 내 솔루션은 해결할 수있는 한 가지 방법을 제공합니다.