方式一

ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
  taskExecutor.execute(new MyTask());
}
taskExecutor.shutdown();
try {
  taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
  ...
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

方式二

CountDownLatch latch = new CountDownLatch(totalNumberOfTasks);
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
  taskExecutor.execute(new MyTask());
}
 
try {
  latch.await();
} catch (InterruptedException E) {
   // handle
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.


方式二在每个线程中加入countDown,需保证一定执行,不然主线程会一直卡住。

try {
            ...
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            countDownLatch.countDown();
        }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

例:

简历一个

        @Slf4j
public class CountDownLatchRunnable implements Runnable {
    private final String command;
    private final CountDownLatch countDownLatch;
 
    public CountDownLatchRunnable(String command, CountDownLatch countDownLatch) {
        this.command = command;
        this.countDownLatch = countDownLatch;
    }
 
    @Override
    public void run() {
        log.info(Thread.currentThread().getName() + " start. Command = " + command);
        processCommand(command);
        log.info(Thread.currentThread().getName() + " finish.");
    }
 
    private void processCommand(String command) {
        log.info(Thread.currentThread().getName() + ":, doing work:" + command);
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            countDownLatch.countDown();
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
public class Run {
 
    public static void main(String[] args) throws InterruptedException {
 
        log.info("Main thread start.");
 
        int theadNum = 3;
        // CountDownLatch 需要将对象传入需要'等待完成'的线程对象中
        CountDownLatch countDownLatch = new CountDownLatch(theadNum);
        ExecutorService executorService = Executors.newFixedThreadPool(theadNum);
        Runnable worker = new CountDownLatchRunnable("Task", countDownLatch);
 
        // 创建5个线程, 提交到线程池
        for (int i = 0; i < theadNum; i++) {
            executorService.execute(worker); // 同一个实例对象
        }
        // 等待所有线程执行完成(线程阻塞)
        countDownLatch.await();
 
        log.info("Main thread finish.");
 
        // 停止接受新任务,当已有任务将执行完,关闭线程池
        executorService.shutdown();
        // 等待线程池中所有的任务执行完成, 前提是执行了 shutdown
        while (!executorService.isTerminated()) {
            // 等待所有线程执行完成
        }
        log.info("exit");
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.