使用 Java Executor 实现多线程

发布于 2024-09-28 09:44:35 字数 1390 浏览 5 评论 0原文

我被以下问题困扰。 假设我有一个包含 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

放血 2024-10-05 09:44:35

简单的解决方案是添加对 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)

}

The easy solution is to add a call to 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)

}
二智少女 2024-10-05 09:44:35

您需要将 threadExecutor.shutdown(); 替换为 threadExecutor.awaitTermination(); 调用 threadExecutor.shutdown()< /code>,您还需要调用threadExecutor.awaitTermination()。前者是非阻塞调用,仅启动关闭,而后者是阻塞调用,实际上等待所有任务完成。由于您使用的是前者,因此您可能会在所有任务完成之前返回,这就是为什么您并不总是能返回所有结果。 Java API 不太清楚,因此有人提交了一个关于此的 bug

You need to replace threadExecutor.shutdown(); with threadExecutor.awaitTermination();. After calling threadExecutor.shutdown(), you need to also call threadExecutor.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.

卷耳 2024-10-05 09:44:35

这里至少有两个问题。

  1. 在您的 main 中,您关闭 ExecutorService,然后尝试立即获取结果。执行器服务将异步执行您的作业,因此很有可能您的所有作业尚未完成。当您调用response.setResult(vectorList)时,vectorList未完全填充。

<罢工>2。您正在从所有可运行对象中同时访问同一个 Vector 对象。这可能会导致 ConcurrentModificationExceptions,或者只是破坏向量中的内容。您需要手动同步 QueryTask 内部的向量,或者传入线程安全容器,例如 Collections.synchronizedList( new ArrayList() );

There are at least 2 issues here.

  1. In your main, you shut down the ExecutorService, then try to get the results out right away. The executor service will execute your jobs asychronously, so there is a very good chance that all of your jobs are not done yet. When you call response.setResult(vectorList), vectorList is not fully populated.

2. You are concurrently accessing the same Vector object from within all of your runnables. This is likely to cause ConcurrentModificationExceptions, 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, like Collections.synchronizedList( new ArrayList() );

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文