我的ExecutorService实现是否正确?

时间:2017-11-08 14:59:45

标签: java multithreading executorservice callable-statement

我是Multithreading的新手,我正在尝试使用ExecutorService让我的程序更快。下面是y实现,但是,我的程序仍然没有快速工作。你能看一下我的代码并提出建议吗?

它基本上会在ArrayList中读取电子邮件地址和商店列表。我使用ExecutorService并遍历ArrayList并调用Callable类进行一些处理并返回一个布尔值。

ArrayList<String> emailAddressList = new ArrayList<>();
ExecutorService executor = Executors.newFixedThreadPool(7);
for (int i = 0; i < emailAddressList.size(); i++) {
    Future<Boolean> resultFromThread =  executor.submit(new Verify(emailAddressList.get(i)));
    bufferedWriter.write(emailAddressList.get(i) + "|" + resultFromThread.get());
    bufferedWriter.newLine();
}

executor.shutdown();
executor.awaitTermination(3, TimeUnit.SECONDS);

=============================================== ============================

public class Verify implements Callable<Boolean> {

    private String email;


    public Verify(String email) {
        this.email = email;
    }

    @Override
    public Boolean call() throws Exception {
        Boolean result = false;
        try {
            result = Validator2.isAddressValid(email);
        } catch (Exception e) {
        }
        return result;
    }

}

2 个答案:

答案 0 :(得分:2)

在循环的每次迭代中,执行两个动作:

  1. Callable计划与Executor一起运行
  2. 在此之后 - 在安排另一个任务之前 - 代码等待执行者完成刚刚提交的Callable。
  3. 这样,所有Callables仍然以串行方式执行(我们等待在提交另一个之前完成一个),而不是并行执行它们。

    一个简单的解决方案可能是首先提交所有可执行的callables。然后,在一个单独的循环中,等待它们完成并处理结果。这样,由于Callables的并行处理,性能将得到改善。

    示例:

    List<Future<Boolean>> futures ... ;
    for (int i = 0; i < emailAddressList.size(); i++) {
        futures.add(executor.submit(new Verify(emailAddressList.get(i))));
    } 
    
    for (int i = 0; i < emailAddressList.size(); i++)
        bufferedWriter.write(emailAddressList.get(i) + "|" + futures.get(i).get());
        bufferedWriter.newLine();
    }
    

    请注意,此代码等待Callables按照提交给Executor的顺序完成。这可能不一定是这种情况。如果结果写入器中的地址顺序不重要,则可以考虑完全异步处理。在Java 8中,这可以使用CompleteableFuture API来实现。

答案 1 :(得分:0)

您已经有效地使代码同步和单线程,而没有使用线程执行程序的任何优势。当调用resultFromThread.get()时,它将阻塞主线程并阻止下一个循环迭代,该循环迭代提交下一个要执行的任务,直到前一个完成。如果您希望提交的验证任务同时运行,则应首先在附加到List<Future<Boolean>>的一个循环中提交所有任务。然后,在另一个循环中,您可以遍历每个循环,然后调用.get(),这样主线程将等待所有执行完成,但不会阻止其他7个线程同时执行。