面试官:如何让主线程等待所有的子线程执行结束之后再执行

java 主线程等待所有子线程执行完毕在执行,在工作总往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总(比如用户下单一个产品,后台会做一系列的处理,为了提高效率,每个处理都可以用一个线程来执行,所有处理完成了之后才会返回给用户下单成功)的场景, 这时候就需要使用线程了。

解决方法

sleep

用 sleep 方法,让主线程睡眠一段时间,让其它子线程先执行,虽然也是解决的方法,但是不推荐使用。

public class ThreadTest extends Thread {

	public static void main(String[] args) throws InterruptedException {
		for(int i = 0;i<10;i++) {
			Thread th = new Thread(new Runnable() {
				public void run() {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("子线程先执行");
				}
			});
			th.start();
		}
		Thread.sleep(5000);
		System.out.println("主线程执行");
	}

}

执行结果如下:
在这里插入图片描述

join()

使用 Thread 的 join() 等待所有的子线程执行完毕,主线程在执行,阻塞的是主线程。

	public static void main(String[] args) throws InterruptedException {
		  Thread t1 = new Thread(() -> {
	            try {
	                Thread.sleep(3000);
	                System.out.println("子线程先执行");
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	        });
	        t1.start();

	        Thread t2 = new Thread(() -> {
	            try {
	                Thread.sleep(3000);
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	        });
	        t2.start();
	        //主线程其他工作完毕,等待子线程的结束, 调用join系列的方法即可
	        t1.join();
	        t2.join();
	        System.out.println("主线程执行");
	}

isTerminated

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

	public static void main(String[] args) throws InterruptedException {
		 ExecutorService pool = Executors.newFixedThreadPool(3);

	        pool.execute(() -> {
	            try {
	                Thread.sleep(2000);
	                System.out.println("子线程先执行");
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	        });


	        //不再接受新的任务
	        pool.shutdown();

	        while (true) {
	            //不推荐(循环效率很低)
	            if (pool.isTerminated()) {
	                System.out.println("线程池中的任务执行结束");
	                break;
	            }
	        }
	        System.out.println("主线程执行");
	}

执行结果如下:

在这里插入图片描述

Future机制

public static void main(String[] args) throws InterruptedException, ExecutionException {
		ExecutorService pool = Executors.newFixedThreadPool(3);

        Future<Integer> task = pool.submit(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("子线程先执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 2;
        });

        //不再接受新的任务
        pool.shutdown();

        //get方法为阻塞获取
        System.out.println("task的运行结果:" + task.get());

        System.out.println("主线程执行");
	}

执行结果如下:
在这里插入图片描述

CountDownLatch

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

public static void main(String[] args) throws InterruptedException, ExecutionException {
		   CountDownLatch latch = new CountDownLatch(1);

	        Thread thread = new Thread(() -> {
	            try {
	                Thread.sleep(3000);
	                System.out.println("子线程先执行");
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            } finally {
	                latch.countDown();
	            }
	        });
	        thread.start();
	        latch.await();
	        System.out.println("主线程");
	}

执行结果如下:

在这里插入图片描述

CompletableFuture

public static void main(String[] args) throws InterruptedException, ExecutionException {
		  CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
	            try {
	                Thread.sleep(2000);
	    	        System.out.println("子线程先执行");
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	            return 2;
	        });

	        CompletableFuture<Integer> cf = CompletableFuture.supplyAsync(() -> {
	            try {
	                Thread.sleep(2000);
	    	        System.out.println("子线程先执行");
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	            return 3;
	        }).thenCombine(cf1, (result1, result2) -> result1 * result2);

	        //get方法为阻塞获取
	        System.out.println("计算结果为" + cf.get());
	        System.out.println("主线程执行");
	}

执行结果如下:
在这里插入图片描述

CyclicBarrier

public static void main(String[] args) throws InterruptedException, ExecutionException, BrokenBarrierException {
		final CyclicBarrier barrier = new CyclicBarrier(5);
		for(int i=0;i<5;i++) {
			Thread thread = new Thread(new Runnable() {
				public void run() {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("子线程先执行");
					try {
						barrier.await();
					} catch (InterruptedException | BrokenBarrierException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			});
			thread.start();
		}
		barrier.await();
		System.out.println("主线程执行");
	}

到这里小伙伴可能会问,countDownLatch 和 cyclicBarrier 有什么区别呢?不妨看一下我这篇文章: JUC下的CountDownLatch,CyclicBarrier、Semaphore的使用方法

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值