栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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 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 cf1 = CompletableFuture.supplyAsync(() -> {
	            try {
	                Thread.sleep(2000);
	    	        System.out.println("子线程先执行");
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	            return 2;
	        });

	        CompletableFuture 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的使用方法

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/704388.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号