如何等待 ExecutorService 中的一个正在运行的线程完成分配另一个任务

Posted

技术标签:

【中文标题】如何等待 ExecutorService 中的一个正在运行的线程完成分配另一个任务【英文标题】:How to wait for one of the running threads in ExecutorService to finish to assign another task 【发布时间】:2018-11-17 01:15:35 【问题描述】:

我有将任务分配给具有固定大小线程的 ExecutorService 的循环,我希望 主程序等待 让 threadPool 释放其中一个线程以分配另一个任务给它。

这是我的示例代码:在此示例代码中,我希望在最后打印 finished! 并希望使用 ExecutorService。

public static void main(String[] args) 
    ExecutorService ex = Executors.newFixedThreadPool(3);


    for(int i=0; i< 100; i++) 

        ex.execute(new TestThread(i)); // I want the program wait here for at least one thread to free

    

    System.out.println("finished!");


private static class TestThread implements Runnable 

    private int i;
    public TestThread(int i) 
        this.i = i;
    

    @Override
    public void run() 

        System.out.println("hi: " + i);
        try 
            Thread.sleep(5000);
         catch (InterruptedException e) 
            e.printStackTrace();
        
    

【问题讨论】:

docs.oracle.com/javase/7/docs/api/java/util/concurrent/… - 你读过javadocs吗? 所以您希望在继续finished 之前完成所有提交给执行程序服务的可运行文件?在您循环提交可运行文件之前、期间和之后,“执行器服务有一个免费工作人员”的条件很可能是正确的 @ScaryWombat 我认为没有理由不将其发布为答案。 【参考方案1】:

我了解您希望正在提交作业的线程在执行程序服务中没有免费、现成的工作线程时阻塞。这对于应用背压很有用。

在核心,执行器服务“简单地”由一个可运行队列和一个工作线程池组成。

您可以通过构建具有固定大小的工作队列(在您的情况下,大小为 1)的执行器服务来获得此行为。

在代码中:(请注意,您的调用者线程在提交最后一个作业后仍将继续;它不会等待该作业完成)

package stackOv;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class BackPressure 
    public static void main(String[] args) 
        // this is the backing work queue; in this case, it is of bounded size
        ArrayBlockingQueue<Runnable> q = new ArrayBlockingQueue<>(1);
        ExecutorService ex = new ThreadPoolExecutor(3, 3, 30, TimeUnit.SECONDS, q,
                new ThreadPoolExecutor.CallerRunsPolicy());
        for(int i=0; i< 100; i++) 
            ex.execute(new TestWork(i));
        
        System.out.println("finished!");
    

    private static class TestWork implements Runnable 
        private int i;
        public TestWork(int i) 
            this.i = i;
        
        @Override
        public void run() 
            System.out.println("hi: " + i);
            try 
                Thread.sleep(100);
             catch (InterruptedException e)  e.printStackTrace(); 
        
    

【讨论】:

【参考方案2】:

你只需要:

ex.awaitTermination();

【讨论】:

以上是关于如何等待 ExecutorService 中的一个正在运行的线程完成分配另一个任务的主要内容,如果未能解决你的问题,请参考以下文章

[Golang]实现一个带有等待和超时功能的协程池 - 类似Java中的ExecutorService接口实现

[Golang]实现一个带有等待和超时功能的协程池 - 类似Java中的ExecutorService接口实现

Executorservice 等待任务完成后

Java ExecutorService:等待终止所有递归创建的任务

Java ExecutorService - 处于等待状态的线程

java中ExecutorService的线程池如何暂停所有的任务和继续所有的任务? 有这样的函数吗?