使用Java执行器的多线程

使用Java执行器的多线程,java,multithreading,executor,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 Execut

我被以下问题困住了。 比如说,我有一个包含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分

有人知道是什么导致了这个问题吗

任何帮助都将不胜感激


谢谢

这里至少有两个问题

在主要步骤中,关闭Executor服务,然后尝试立即获得结果。executor服务将异步执行您的作业,因此很有可能您的所有作业尚未完成。调用response.setResultvectorList时,向量列表未完全填充。
二,。您正在从所有Runnable中同时访问同一个Vector对象。这可能会导致ConcurrentModificationException,或者仅仅是向量中的混乱内容。您需要手动同步QueryTask内部的向量,或者传入线程安全容器,如Collections.synchronizedList new ArrayList

您需要更换threadExecutor.shutdown;使用threadExecutor.awaitTermination;。调用threadExecutor.shutdown后,还需要调用threadExecutor.shutdown。前者是只启动关机的非阻塞调用,而后者是实际等待所有任务完成的阻塞调用。因为您使用的是前者,所以您可能在所有任务完成之前返回,这就是为什么您不总是返回所有结果的原因。Java API不太清楚,因此有人对此提出了质疑。

简单的解决方案是添加对ExecutorService.com的调用

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)

}

@史蒂文-谢谢。一般来说,我想到的是列表,我忘记了向量,我个人从来不使用这个类。在这里如何使用它是可以的,但是如果QueryTask所做的事情比仅仅添加到它(即,在它上面进行迭代)更复杂,那么您仍然需要一些额外的并发控制,即使向量是同步的。错误的,OP需要两个调用。看起来您是对的:关闭和等待终止都是必要的。JavaDoc页面并没有让这一点变得太明显,而且这些方法的名称也很糟糕,但顶部的代码示例包括一个有助于澄清问题的ShutdownAndWaitTermination方法。@Tim编辑了原始帖子。事实上,这就是罪魁祸首。我根据Tim的建议添加了终止,现在它确实起作用了。非常感谢。整个过程本身已经很快了。比如说1000件物品只需1秒,但我只是贪心,想让它更快。当我实现这种多线程方法时,结果似乎和单线程并没有太大的不同,因为存在终止调用。使用此awaitTermination可以加快进程速度吗?使用ExecutorService.submitCallable并按照@John Guaghan的建议迭代返回的未来对象可能会稍微快一点,但不要调用awaitTermination,这是不必要的。您可能还想了解Map Reduce,这正是您在这里所做的工作。