使用Java Executor进行多线程处理

时间:2010-10-21 22:04:09

标签: java multithreading 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。 在流程结束时,我希望将所有结果都包含在Vector列表中。

我在响应中不断得到不一致的结果。 例如,如果我传递带有10个名字的请求,我只会返回3或4,或者有时在响应中没有任何内容。 我期待如果我超过10,那么我将得到10回。

有谁知道导致问题的原因是什么?

任何帮助都会受到赞赏。

由于

3 个答案:

答案 0 :(得分:3)

简单的解决方案是添加对ExecutorService.awaitTermination()

的调用
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();
      threadExecutor.awaitTermination(aReallyLongTime,TimeUnit.SECONDS);

      response.setResult(vectorList)

}

答案 1 :(得分:2)

您需要将threadExecutor.shutdown();替换为threadExecutor.awaitTermination();致电threadExecutor.shutdown()后,您需要致电{{1} }。前者是非阻塞调用,只是启动关闭,而后者是阻塞调用,实际上等待所有任务完成。由于您使用的是前者,因此您可能在所有任务完成之前返回,这就是为什么您并不总能收回所有结果的原因。 Java API不太清楚,因此有人就此提出了bug

答案 2 :(得分:0)

这里至少有两个问题。

  1. 在您的主体中,您关闭了ExecutorService,然后尝试立即获得结果。执行程序服务将异步执行您的作业,因此很有可能您的所有作业尚未完成。当您调用response.setResult(vectorList)时,vectorList未完全填充。
  2. <击> 2。您同时从所有runnables中访问相同的Vector对象。这可能会导致ConcurrentModificationExceptions,或者仅仅是向量中的clobber内容。您需要手动同步QueryTask内部的向量,或者传入一个线程安全的容器,如Collections.synchronizedList( new ArrayList() );