zoukankan      html  css  js  c++  java
  • 主线程等待所有的子线程结束之后再执行?(转)

    转自:https://www.jianshu.com/p/ba8a518c02c3

    一、使用Thread的join方法

    join()方法使得主线程等待子线程执行结束,阻塞的是主线程。

    package com.qcy.testThreadFinish;
    
    /**
     * @author qcy
     * @create 2020/09/09 17:05:23
     */
    public class Case1 {
        public static void main(String[] args) throws InterruptedException {
    
            Thread t1 = new Thread(() -> {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            t1.start();
    
            Thread t2 = new Thread(() -> {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            t2.start();
    
            t1.join();
            t2.join();
            System.out.println("主线程结束");
        }
    }

    二、使用线程池的isTerminated方法

    isTerminated,当调用shutdown()方法后,并且所有提交的任务完成后才会返回为true

    这里直接使用了固定大小的线程池,线程池的参数在面试中也经常被问到。

    package com.qcy.testThreadFinish;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * @author qcy
     * @create 2020/09/09 17:05:23
     */
    public class Case2 {
        public static void main(String[] args) {
    
            ExecutorService pool = Executors.newFixedThreadPool(3);
    
            pool.execute(() -> {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
    
            pool.execute(() -> {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
    
            //不再接受新的任务
            pool.shutdown();
    
            while (true) {
                //手动循环确实效率很低,不推荐
                if (pool.isTerminated()) {
                    System.out.println("线程池中的任务执行结束");
                    break;
                }
            }
            System.out.println("主线程结束");
        }
    }

    三、使用Future机制

    package com.qcy.testThreadFinish;
    
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * @author qcy
     * @create 2020/09/09 17:05:23
     */
    public class Case4 {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    
            ExecutorService pool = Executors.newFixedThreadPool(3);
    
            Future<Integer> task1 = pool.submit(() -> {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return 2;
            });
    
            Future<Integer> task2 = pool.submit(() -> {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return 3;
            });
    
            //不再接受新的任务
            pool.shutdown();
    
            //get方法为阻塞获取
            System.out.println("task1的运行结果:" + task1.get());
            System.out.println("task2的运行结果:" + task2.get());
    
            System.out.println("主线程结束");
        }
    }

    四、使用CountDownLatch

    每调用一次countDown方法,计数器会减1,在计数器减为0之前,await方法将会阻塞主线程。

    package com.qcy.testThreadFinish;
    
    import java.util.concurrent.CountDownLatch;
    
    /**
     * @author qcy
     * @create 2020/09/09 17:05:23
     */
    public class Case5 {
        public static void main(String[] args) throws InterruptedException {
    
            CountDownLatch latch = new CountDownLatch(2);
    
            Thread t1 = new Thread(() -> {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    latch.countDown();
                }
            });
            t1.start();
    
            Thread t2 = new Thread(() -> {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    latch.countDown();
                }
            });
            t2.start();
    
            latch.await();
            System.out.println("主线程结束");
        }
    }

    五、使用CompletableFuture

    等到两个子任务都完成后,输出两数之积,再执行主线程

    package com.qcy.testThreadFinish;
    
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutionException;
    
    /**
     * @author qcy
     * @create 2020/09/09 17:05:23
     */
    public class Case6 {
        public static void main(String[] args) throws InterruptedException, ExecutionException {
    
            CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return 2;
            });
    
            CompletableFuture<Integer> cf = CompletableFuture.supplyAsync(() -> {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return 3;
            }).thenCombine(cf1, (result1, result2) -> result1 * result2);
    
            //get方法为阻塞获取
            System.out.println("计算结果为" + cf.get());
            System.out.println("主线程结束");
        }
    }
  • 相关阅读:
    luogu P1455 搭配购买
    浅谈筛素数
    luogu P1205 方块转换
    luogu P2241 统计方形
    luogu P1866 编号
    luogu P1042 乒乓球
    4.7清明考试(完蛋)
    LINUX 启动图形界面和查看运行级别
    密钥登录LINUX步骤
    服务命令只支持基本的LSB操作(启动、停止、重新启动、尝试重启、重新加载、强制重新加载、状态)。对于其他操作,请尝试使用systemctl。
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/15108955.html
Copyright © 2011-2022 走看看