java 等待线程/线程池执行完毕

1.单线程开始并执行完毕
当线程开始后,需要用到join的方法
不废话直接贴代码

   public static void main(String args[]) {
        long begin = System.currentTimeMillis();
        System.out.println(begin);
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("111");
            }
        });
        try {
            thread.start();
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println(end-begin);
        System.out.println("执行完毕");
    }

运行结果:

1502091332017
111
1002
执行完毕

现在我们来看一下join这个方法

    /**
     * Waits for this thread to die.
     *
     * <p> An invocation of this method behaves in exactly the same
     * way as the invocation
     *
     * <blockquote>
     * {@linkplain #join(long) join}{@code (0)}
     * </blockquote>
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final void join() throws InterruptedException {
        join(0);
    }
    翻译为中文大意就是,等待线程执行完毕!

2.等待线程池执行完毕
等待线程池执行完毕我们需要用到
CountDownLatch这个类
且看代码:

    public static void main(String args[]) throws InterruptedException {
        final CountDownLatch count = new CountDownLatch(3);
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        try {
            long begin = System.currentTimeMillis();
            System.out.println(begin);
            fixedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000L);
                        count.countDown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("111");
                }
            });
            fixedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(2000L);
                        count.countDown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("222");
                }
            });
            fixedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(3000L);
                        count.countDown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("333");
                }
            });

            count.await();
            long end = System.currentTimeMillis();
            System.out.println(end-begin);
            System.out.println("执行完毕");
        } finally {
            fixedThreadPool.shutdown();
        }
    }

最后一定要记得线程池关闭, 要不会出大问题的
运行结果:

1502091739441
111
222
333
3002
执行完毕
<think>好的,我现在需要帮助用户解决Java中主线程如何等待线程池执行完成的问题。用户提到了join方法、shutdown和awaitTermination,我需要结合这些关键词给出清晰的解答。首先,我应该回忆一下Java线程的相关知识,特别是线程池的管理和同步机制。 首先,用户提到的join方法。我记得Thread类的join方法可以让主线程等待线程结束,但线程池中的线程通常是通过ExecutorService管理的,不能直接获取到每个线程的引用,所以直接使用join可能不太适用。这点需要说明清楚,避免用户混淆。 然后是shutdown和awaitTermination。线程池的shutdown方法会启动有序关闭,不再接受新任务,但已提交的任务会继续执行。而awaitTermination则是阻塞主线程,直到所有任务完成或者超时。不过要注意,shutdown之后必须调用awaitTermination才能真正等待,否则主线程可能立即继续执行。同时,需要处理可能的InterruptedException异常。 接下来,用户可能没有提到的其他方法,比如CountDownLatch。这是并发工具类中的一个同步辅助器,可以在每个任务完成时递减计数器,主线程等待计数器归零。这种方法更灵活,尤其适用于需要明确知道所有任务完成的场景。此外,Future的get方法也可以用来等待任务完成,但如果是多个任务的话,可能需要遍历所有Future对象,逐一调用get,这可能会比较繁琐,或者使用invokeAll方法。 还有,使用shutdown结合isTerminated轮询检查的方法,虽然不推荐,但在某些情况下可能适用。需要指出这种方法的缺点,比如忙等待可能消耗CPU资源。 现在需要整理这些方法,按推荐的顺序进行说明,可能从最基础的Thread.join到高级工具类。但考虑到用户的问题是关于线程池的,应该重点放在ExecutorService的方法和CountDownLatch上。 需要注意的是,线程池中的线程默认是守护线程,如果主线程等待的话,可能会提前退出,导致子线程未完成就被终止。因此,正确的等待机制非常重要。 另外,需要给出示例代码,帮助用户理解如何具体实现。比如使用awaitTermination时,先调用shutdown,然后循环调用awaitTermination,直到返回true或者超时。或者使用CountDownLatch,在每个任务完成时调用countDown()。 可能还需要比较不同方法的优缺点,比如使用CountDownLatch可以更精确地控制,而awaitTermination依赖于线程池的正确关闭。同时,要提醒用户处理异常情况,比如任务执行中抛出异常,是否会影响等待机制。 最后,生成相关问题,比如如何判断线程池是否完成,或者如何处理任务中的异常,这些都能帮助用户进一步学习。</think>在Java中,主线程等待线程池执行完毕主要有以下四种实现方式,按推荐优先级排序: ### 一、使用`awaitTermination`方法(推荐) 1. 调用`shutdown()`关闭线程池 2. 配合`awaitTermination()`实现等待 ```java ExecutorService executor = Executors.newFixedThreadPool(4); // 提交任务... executor.shutdown(); // 停止接收新任务 try { // 循环等待直到所有任务完成 while (!executor.awaitTermination(60, TimeUnit.SECONDS)) { System.out.println("等待任务完成..."); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } ``` **优势**:官方推荐方式,可设置超时时间避免无限阻塞[^2] ### 二、使用`CountDownLatch`(精确控制) 1. 创建计数器(任务数量为初始值) 2. 每个任务完成后计数器减1 ```java CountDownLatch latch = new CountDownLatch(10); ExecutorService executor = Executors.newFixedThreadPool(4); for (int i = 0; i < 10; i++) { executor.submit(() -> { try { // 执行任务... } finally { latch.countDown(); // 必须放在finally块 } }); } try { latch.await(); // 主线程等待 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } ``` **特点**:精确控制等待的任务数量,适合已知任务总数的情况[^3] ### 三、使用`Future`+`get()`方法 ```java List<Future<?>> futures = new ArrayList<>(); ExecutorService executor = Executors.newFixedThreadPool(4); for (int i = 0; i < 10; i++) { futures.add(executor.submit(() -> { // 执行任务... })); } try { for (Future<?> future : futures) { future.get(); // 阻塞获取结果 } } catch (ExecutionException | InterruptedException e) { // 异常处理 } ``` ### 四、不推荐的方式:`join`方法 $$注意:线程池中的工作线程无法直接获取Thread对象,因此join方法不适用于线程池场景$$ ### 对比表格 | 方法 | 适用场景 | 超时控制 | 异常处理 | 资源释放 | |--------------------|-------------------------|--------|--------|--------| | awaitTermination | 通用场景 | 支持 | 自动 | 自动 | | CountDownLatch | 精确控制任务数量 | 支持 | 手动 | 手动 | | Future.get() | 需要获取任务结果 | 支持 | 自动 | 自动 | | isTerminated轮询 | 需要实时监控 | 支持 | 手动 | 自动 | **最佳实践建议**:优先使用`awaitTermination`+`shutdown`组合,需要获取任务结果时配合`Future`使用,精确控制任务完成数量时使用`CountDownLatch`[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值