【问题标题】:Processing with Threadpool and executor service使用 Threadpool 和 executor 服务进行处理
【发布时间】:2018-07-19 10:34:18
【问题描述】:

我有一个包含 10 个元素的 ArrayList。我启动了一个大小为 10 的线程池,并使用传递给每个线程的元素调用执行。每个线程将该元素作为输入进行一些处理并输出结果。问题是,输出有时只有 7 个元素的处理结果,有时有 8 个元素,有时有一些重复,有时有 9 个元素。我不确定为什么我没有正好 10 个元素的处理结果。这是我的代码sn-p。

ExecutorService exeSvc = 
                Executors.newFixedThreadPool(10)
for (Object element: arlList)//arlList is the arraylist of 
                                                           size-10
{
   exeSvc.execute({->myRunnable element});
}

我做错了什么?

【问题讨论】:

  • 如果可能的话,你能添加输出吗?
  • 如果一个线程完成了一项工作,它会立即执行下一个工作,所以有时第一个线程会在最后一个线程创建之前完成 2 个工作。这就是你有重复的原因。
  • "exeSvc.execute({->myRunnable element});" - 这不会编译。
  • 试试这样的for (Object element: arlList) { Runnable worker = new WorkerThread(); executor.execute(worker); } executor.shutdown();
  • 1.为什么它被标记为groovy? 2. 在for 中声明局部变量为element 变量的副本,并使用execute({}) 中的副本。 3.使用execSvc.shutdown() && awaitTermination()等待所有执行完成

标签: java multithreading groovy threadpool threadpoolexecutor


【解决方案1】:

时髦的...

import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit

ExecutorService exeSvc = Executors.newFixedThreadPool(5)
for (int element=0;element<9;element++) {
    int elementCopy = element
    exeSvc.execute({->
        Thread.sleep(567); 
        println "${Thread.currentThread()}  element = $element elementCopy = $elementCopy"; 
    });
}
println "All Started"
exeSvc.shutdown()
exeSvc.awaitTermination(10, TimeUnit.SECONDS)
println "All Finished"

输出

All Started
Thread[pool-12-thread-1,5,main]  element = 9 elementCopy = 0
Thread[pool-12-thread-2,5,main]  element = 9 elementCopy = 1
Thread[pool-12-thread-3,5,main]  element = 9 elementCopy = 2
Thread[pool-12-thread-4,5,main]  element = 9 elementCopy = 3
Thread[pool-12-thread-5,5,main]  element = 9 elementCopy = 4
Thread[pool-12-thread-1,5,main]  element = 9 elementCopy = 5
Thread[pool-12-thread-2,5,main]  element = 9 elementCopy = 6
Thread[pool-12-thread-3,5,main]  element = 9 elementCopy = 7
Thread[pool-12-thread-4,5,main]  element = 9 elementCopy = 8
All Finished

正如您在我的例子中看到的那样,for 循环在线程启动之前完成,并且所有这些循环的 element 值为 9,而 elementCopy 不同

【讨论】:

  • 谢谢!这确实解决了我的问题。我所要做的就是将元素复制到 for 循环内的局部变量中。太好了!!!
【解决方案2】:

那是因为main threadExecutorService 完成得更早。

要强制Main thread 等待ExecutorService 完成处理,请使用:

exeSvc.awaitTermination(5, TimeUnit.SECONDS); //this will 5 second to finish all tasks
exeSvc.shutdown();

【讨论】:

  • 这假定池中的线程是守护线程。
【解决方案3】:

每个元素的执行时间不一样。因此,在进程结束时,需要关闭线程。你可以使用,

if ( check_whether_operation_is_done ) {
    Logger.info( "Process shutdown" );
    exeSvc.shutdownNow();
}

【讨论】:

  • 这没有回答问题。此外,您应该在最后一个作业提交到池后调用shutdown()(而不是shutdownNow())。
猜你喜欢
  • 2019-01-07
  • 2019-03-27
  • 1970-01-01
  • 2015-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
相关资源
最近更新 更多