Java ExecutorService获取所有任务的反馈

时间:2012-10-29 15:42:49

标签: java executorservice

我想向多个(500,1000,2000)用户发送电子邮件。

我使用ExecutorService完成了这项工作。

但现在我想收集所发送的成功电子邮件的数量以及总记录中失败的电子邮件数量。

我已经实现了这个:

int startValue=0;
int endValue=0;
List userEmailList = getListFromDB();
ExecutorService  e = Executors.newFixedThreadPool(10);
Collection c = new ArrayList();

while (someflag) 
{  
// in MyTask class I am sending email to users.
c.add(new MyTask(startValue, endValue,userEmailList));  
}    
e.invokeAll(c);   //Here I am calling invokeall .
pool.shutdown();


public class MyTask implements Callable<String> { 
  MyTask(startValue, endValue,userEmailList){
  }

  public String call(){
//e.g.   batch 1 will have  - startValue => endValue   = 0 -100
//e.g.   batch 2 will have  - startValue => endValue   = 101 -199
//e.g.   batch 3 will have  - startValue => endValue   = 200 -299
//e.g.   batch 4 will have  - startValue => endValue   = 300 -399
//e.g.   batch 5 will have  - startValue => endValue   = 400 - 499

for(int i=startValue;i<endValue;i++){
      sendEmailToUser(userEmailList.get(i)){
}
 }

}

但是future.get()返回完成的任务数量。所以从上面的代码中它将返回5个任务。

但我希望输出的电子邮件数量不足以及发送的成功电子邮件数量。

例如,如果有500个电子邮件用户,如果有20个被罚款,则输出应该是480次成功,20次失败。

但是使用上面的代码我只能得到任务。即5个任务

有人能告诉我如何从所有并发任务中获得反馈(完成的任务数量)。

2 个答案:

答案 0 :(得分:1)

您的MyTask会返回String(实施Callable<String>),这在您的情况下没有多大意义。您可以自由返回您想要的任何其他类型。不幸的是,你需要一些简单的POJO来包含结果,例如:

public class Result {

    private final int successCount;
    private final int failureCount;

    public Result(int successCount, int failureCount) {
        this.successCount = successCount;
        this.failureCount = failureCount;
    }

}

在完成给定批处理后返回它(实现Callable<Result>)。当然,您的MyTask必须跟踪失败的电子邮件数量并返回Result周围的正确值。

但是我看到了几种改进代码的方法。首先,不要将startValue, endValue范围传递给MyTask,而只使用userEmailList.subList(startValue, endValue) - 这将简化您的代码很多

new MyTask(userEmailList.subList(startValue, endValue));
//...

public class MyTask implements Callable<Result> { 
    MyTask(userEmailList){
    }

    public Result call(){
        for(email: userEmailList) {
            sendEmailToUser(email);
            //collect results here
        }
        return new Result(...);
    }
 }

另一方面,创建MyTask只发送一封电子邮件没有错。您只需检查一个任务(一个电子邮件)的结果 - 无论是否为异常(或单个Boolean),而不是聚合给定批次中的计数。它更容易,也不应该慢。

答案 1 :(得分:0)

我可以看到你的调用方法被声明为返回一个String但你的代码没有返回任何东西(可能是不完整的片段)。从您的陈述中,我了解到您将返回任务是否完成,而不是邮件是否已发送。您可以使sendEmailToUser返回失败成功,具体取决于邮件是否已成功发送并使用Future.get

获取结果