我是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;
}
}
在循环的每次迭代中,执行两个操作:
- 可调用程序计划与执行程序一起运行
- 紧接着,在安排另一个任务之前,代码会等待Executor完成刚刚提交的Callable
这样,所有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来实现。
您已经有效地使代码同步和单线程化,而使用线程执行器没有任何优势。当调用resultFromThread.get()时,它将阻塞主线程,并阻止提交下一个要执行的任务的下一个循环迭代运行,直到上一个迭代完成。如果希望提交的验证任务同时运行,则应在附加到List<Future<Boolean>>
的一个循环中首先提交所有任务。然后,在另一个循环中,您可以遍历其中的每一个,然后调用.get(),这样主线程将等待所有执行的完成,但不会阻止其他7个线程同时执行。