Java基础 -- 多线程的使用,执行完所有子线程,再继续执行主线程

在这里插入图片描述


在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


1. 场景描述

  • 在开发过程中,对一些大数据量的操作,往往会使用多线程,但是我们想在这些任务执行完成后,才接着再执行的话,就需要使用下面这些手段,不然主线程结束了,子线程也就结束了。
  • 重点:在实际生产过程中,因为每条线程都有逻辑要处理,所以线程的数量并不能随便设定,还要参考电脑虚拟内存的大小,比如我的电脑已经开启了很多应用,现在本地测试还想开20条线程,可是通过log发现,我的程序在目前状态只能开启最多10条线程。

2. CountDownLatch

2.1 Introduction

  • 这个类使一个线程等待其他线程各自执行完毕后再执行。是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,countdownLatch.countDown()计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,在CountDownLatch上await()的线程就会被唤醒,然后继续执行下面的工作。

2.2 Code

    public class CountDownLatchThead extends Thread {
        private int num;
        private CountDownLatch countDownLatch;

        public CountDownLatchThead(int num,CountDownLatch countDownLatch) {
            this.num = num;
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            super.run();
            System.out.println("the thread num is :"+num);
            try {
                Thread.sleep(10 * 1000);
                System.out.println("我睡了10s,the thread num is :"+num);
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

2.3 Test

	public void demo04() throws  InterruptedException{
	     CountDownLatch countDownLatch = new CountDownLatch(10);
	     for (int i = 0; i < 10; i++) {
	         Thread thread = new CountDownLatchThead(i,countDownLatch);
	         thread.start();
	     }
	     countDownLatch.await();
	     System.out.println("子线程执行完,主线程继续执行");
	} 

3. CyclicBarrier

  • 我服了,这个鬼东西一直没达到我想要的效果 2023-2-28

3.1 Introduction

  • CyclicBarrier 的源码实现和 CountDownLatch 大同小异,CountDownLatch 基于 AQS 的共享模式的使用,而 CyclicBarrier 基于 Condition 来实现的。在CyclicBarrier类的内部有一个计数器,允许一组线程到达某个栅栏点(common barrier point)互相等待,直到最后一个线程到达栅栏点,栅栏才会打开,处于阻塞状态的线程恢复继续执行。每个线程在到达屏障点的时候都会调用await方法将自己阻塞,此时计数器会减1,当计数器减为0的时候所有因调用await方法而被阻塞的线程将被唤醒。这就是实现一组线程相互等待的原理。

3.2 Code

    public class CyclicBarrierThead extends Thread {
        private int num;
        private CyclicBarrier cyclicBarrier;

        public CyclicBarrierThead(int num,CyclicBarrier cyclicBarrier) {
            this.num = num;
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            super.run();
            System.out.println("the thread num is :"+num);
            try {
                Thread.sleep(10 * 1000);
                System.out.println("CyclicBarrier,我睡了10s,the thread num is :"+num);
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }

3.3 Test

     public void demo06() throws  Exception{
        CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
        for (int i = 0; i < 10; i++) {
            Thread thread = new CyclicBarrierThead(i,cyclicBarrier);
            thread.start();
        }
        //cyclicBarrier.await();
        System.out.println("子线程执行完,主线程继续执行");
    }
 

3.4 CountDownLatch和CyclicBarrier的比较

  • 1.CountDownLatch是线程组之间的等待,即一个(或多个)线程等待N个线程完成某件事情之后再执行;而CyclicBarrier则是线程组内的等待,即每个线程相互等待,即N个线程都被拦截之后,然后依次执行。
  • 2.CountDownLatch是减计数方式,而CyclicBarrier是加计数方式。
  • 3.CountDownLatch计数为0无法重置,而CyclicBarrier计数达到初始值,则可以重置。
  • 4.CountDownLatch不可以复用,而CyclicBarrier可以复用。

4. ThreadPool

    public static void main(String[] args) throws Exception {
        int N = 10;// 线程个数
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(N);
        for (int i = 0; i < N; i++) {
            fixedThreadPool.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        System.out.println("子线程结束");
                    }
                }
            });
        }
        //停止接收外部submit的任务
        fixedThreadPool.shutdown();
        // 等待子线程结束,再继续执行下面的代码
        fixedThreadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);//阻塞,等待所有子线程执行完成
        System.out.println("结束");
    }

5. Awakening

         在一秒钟内看到本质的人和花半辈子也看不清一件事本质的人,自然是不一样的命运。
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百世经纶『一页書』

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值