Java ExecutorService获取所有任务的反馈

3

我想要给多个用户(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个任务

有人能告诉我如何获取所有并发任务的反馈(而不是完成的任务数量)吗?


请问您能否发布完整的代码片段?我认为您需要将返回类型设置为List<String>而不仅仅是String - Amit Deshpande
2个回答

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)。这样做更容易,而且不应该更慢。


0

我看到你的调用方法声明要返回一个字符串,但是你的代码没有返回任何东西(可能是不完整的片段)。从你的陈述中,我理解你返回的是任务是否完成,而不是邮件是否发送成功。你可以让sendEmailToUser根据邮件是否成功发送来返回成功或失败,并使用Future.get获取结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接