使用 Java Executor 实现多线程
我被以下问题困扰。 假设我有一个包含 1000 个项目的请求,我想利用 Java Executor 来解决这个问题。
这是主要方法
public static void main(String[] args) {
//Assume that I have request object that contain arrayList of names
//and VectorList is container for each request result
ExecutorService threadExecutor = Executors.newFixedThreadPool(3);
Vector<Result> vectorList = new Vector<Result();
for (int i=0;i<request.size();i++) {
threadExecutor.execute(new QueryTask(request.get(i).getNames, vectorList)
}
threadExecutor.shutdown();
response.setResult(vectorList)
}
这是 QueryTask 类
public QueryTask() implements Runnable {
private String names;
private Vector<Result> vectorList;
public QueryTask(String names, Vector<Result> vectorList) {
this.names = names;
this.vectorList = vectorList;
}
public void run() {
// do something with names, for example, query database
Result result = process names;
//add result to vectorList
vectorList.add(result);
}
}
因此,基于上面的示例,我想为请求中的每个数据创建线程池,同时运行它,并将结果添加到 VectorList。 在该过程结束时,我希望所有结果都已在向量列表中。
我在响应中不断得到不一致的结果。 例如,如果我传递包含 10 个名称的请求,我只会返回 3 或 4 个名称,或者有时在响应中什么也没有。 我原以为如果我通过了10分,那么我就会拿回10分。
有谁知道导致问题的原因是什么?
任何帮助将不胜感激。
谢谢
I am stuck with this following problem.
Say, I have a request which has 1000 items, and I would like to utilize Java Executor to resolve this.
Here is the main method
public static void main(String[] args) {
//Assume that I have request object that contain arrayList of names
//and VectorList is container for each request result
ExecutorService threadExecutor = Executors.newFixedThreadPool(3);
Vector<Result> vectorList = new Vector<Result();
for (int i=0;i<request.size();i++) {
threadExecutor.execute(new QueryTask(request.get(i).getNames, vectorList)
}
threadExecutor.shutdown();
response.setResult(vectorList)
}
And here is the QueryTask class
public QueryTask() implements Runnable {
private String names;
private Vector<Result> vectorList;
public QueryTask(String names, Vector<Result> vectorList) {
this.names = names;
this.vectorList = vectorList;
}
public void run() {
// do something with names, for example, query database
Result result = process names;
//add result to vectorList
vectorList.add(result);
}
}
So, based on the example above, I want to make thread pool for each data I have in the request, run it simultaneously, and add result to VectorList.
And at the end of the process, I want to have all the result already in the Vector list.
I keep getting inconsistent result in the response.
For example, if I pass request with 10 names, I am getting back only 3 or 4, or sometimes nothing in the response.
I was expecting if I pass 10, then I will get 10 back.
Does anyone know whats causing the problem?
Any help will be appreciate it.
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
简单的解决方案是添加对 ExecutorService.awaitTermination() 的调用
The easy solution is to add a call to ExecutorService.awaitTermination()
您需要将调用threadExecutor.shutdown();
替换为threadExecutor.awaitTermination();
。threadExecutor.shutdown()< /code>,您还需要调用
threadExecutor.awaitTermination()
。前者是非阻塞调用,仅启动关闭,而后者是阻塞调用,实际上等待所有任务完成。由于您使用的是前者,因此您可能会在所有任务完成之前返回,这就是为什么您并不总是能返回所有结果。 Java API 不太清楚,因此有人提交了一个关于此的 bug 。You need to replaceAfter callingthreadExecutor.shutdown();
withthreadExecutor.awaitTermination();
.threadExecutor.shutdown()
, you need to also callthreadExecutor.awaitTermination()
. The former is a nonblocking call that merely initiates a shutdown whereas the latter is a blocking call that actually waits for all tasks to finish. Since you are using the former, you are probably returning before all tasks have finished, which is why you don't always get back all of your results. The Java API isn't too clear, so someone filed a bug about this.这里至少有两个问题。
<罢工>2。您正在从所有可运行对象中同时访问同一个 Vector 对象。这可能会导致 ConcurrentModificationExceptions,或者只是破坏向量中的内容。您需要手动同步 QueryTask 内部的向量,或者传入线程安全容器,例如
Collections.synchronizedList( new ArrayList() );
There are at least 2 issues here.
2. You are concurrently accessing the same Vector object from within all of your runnables. This is likely to causeConcurrentModificationExceptions
, or just clobber stuff in the vector. You need to either manually synchronize on the vector inside of QueryTask, or pass in a thread-safe container instead, likeCollections.synchronizedList( new ArrayList() );