Java:如何让完成的线程从 运行 线程中获取任务

Java: How to get finished threads to pickup tasks from running threads

我正在开发一个多线程应用程序,其任务的 运行 时间各不相同。当一个线程结束时,有没有办法让它从静止的 运行ning 线程接管一些任务?

这是一个例子。我用 5 个线程启动我的程序,每个线程有 50 个任务。当最快的 运行ning 线程完成时,另一个线程仍有 40 个任务要完成。我怎样才能让完成的线程从另一个线程接管 20 个任务,这样每个线程继续处理 20 个任务,而不是等待 运行ning 线程完成剩余的 40 个任务?

最好使用ThreadPoolExecutor。它会自动将任务分配给空闲线程。

使用线程池,这是由于 Executors class:

 ExecutorService es = Executors.newFixedThreadPool(5);
 List<Runnable> tasks = // create your 50 runnable
 List<Future<?>> futures = new ArrayList<>(tasks.size());
 for(Runnable r : tasks) {
     Future<?> f = es.submit(t);
     futures.add(f);
 }

文档很好地解释了它是如何工作的,所以我建议你看一下。

使用ForkJoinPool

A ForkJoinPool differs from other kinds of ExecutorService mainly by virtue of employing work-stealing: all threads in the pool attempt to find and execute subtasks created by other active tasks (eventually blocking waiting for work if none exist). This enables efficient processing when most tasks spawn other subtasks (as do most ForkJoinTasks). When setting asyncMode to true in constructors, ForkJoinPools may also be appropriate for use with event-style tasks that are never joined.

Java8在Executors

中多了一个API
static ExecutorService  newWorkStealingPool()

Creates a work-stealing thread pool using all available processors as its target parallelism level.

查看 Ilya Grigorikigvtia article 了解更多详情。

看看其他相关的 java concurrent API @ tutorials like ThreadPoolExecutor, ExecutorService etc.

不允许线程承担多个任务。这样,任何完成其任务的线程都会接受队列中的下一个可用任务。这些线程不会为每个任务创建新线程,而是被重新使用,因此开销很小。

考虑 - 2 个线程各有 20 个任务,如果第一个线程尚未完成,您希望第二个线程接管第一个线程的任务。将此与队列中有 40 个任务由 2 个线程服务相比,这意味着任务总是会尽快执行,而无需尝试在线程之间移动它们的复杂性。

我没有看到问题中的逻辑 - 如果您有一些任务组由于排序问题而无法进行多线程处理(这是我可以看到提交本身就是一个组的任务的唯一原因任务放到队列中),那么你不能让另一个线程接管未完成的处理(因为那样的话整个组的顺序将被打破)。如果不需要顺序处理,那就把所有的任务都扔进队列,让它们尽快执行。

如果您总是希望给定组中的任务更快执行,请为它们分配更高的优先级并使用由多个线程提供服务的优先级队列。