多线程

守护线程

Java的main是普通线程,并不是守护线程,

守护线程会等待所有的线程执行结束后再结束

线程同步

https://www.jianshu.com/p/2394317257ec

https://www.jianshu.com/p/988bfceadb62

https://www.jianshu.com/p/6f98f03430eb

https://www.cnblogs.com/williamjie/p/9099141.html

Java 主线程等待所有子线程执行完毕

Java 主线程等待所有子线程执行完毕再执行。

  1. 用sleep() 让主线程睡眠一段时间,但是这个睡眠时间是主观设置的,是有我们自己主观设定的,所以不推荐使用。

     1public static void main(String[] args) throws InterrupteException{
     2  for(int i=0; i<5;i++){
     3    new Thread(
     4      new Runnable(){
     5        public void run(){
     6          try{
     7            Thread.sleep(1000);
     8          }catch(InterruptException e){
     9            e.preintStrackTrace();
    10          }
    11          System.out.println("子线程执行!");
    12        }
    13      }
    14    ).start();
    15  }
    16  Thread.sleep(5000);
    17  System.out.println("主线程执行!");
    18}
    
  2. 使用Thread的jion()等待所有的子线程执行完毕,主线程再执行,thread.jion()把指定线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在B中调用了线程A的jion()方法,直到线程A执行完毕后,才会继续执行线程B。

 1public static void main(String[] args) throws InterrupteException{
 2  Vector<Thread> threadVector = new Vector<>();
 3  for(int i=0; i<5;i++){
 4    Thread childThread = new Thread(
 5      new Runnable(){
 6        public void run(){
 7          try{
 8            Thread.sleep(1000);
 9          }catch(InterruptException e){
10            e.preintStrackTrace();
11          }
12          System.out.println("子线程执行!");
13        }
14      }
15    );
16    threadVector.add(childThread);
17    childThread.start();
18  }
19  for(Thread thread: threadVector){
20    thread.jion();
21  }
22  System.out.println("主线程执行!");
23}
  1. 等待多线程完成的CountDownLatch

     1public static void main(String[] args) throws InterruptedException{
     2  final CountDownLatch latch = new CountDownLatch(5);
     3  for(int i =0; i<5; i++){
     4    new Thread(new Runnable(){
     5      public void run(){
     6        try{
     7          Thread.sleep(1000);
     8        }catch(InterruptException e){
     9          e.printStackTrace;
    10        }
    11        System.out.println("子线程执行!");
    12        latch.countDown(); // 让Latch 中的数值减1
    13      }
    14    }).start;
    15    latch.await(); // 阻塞当前线程直到latch中的值为0
    16    System.out.println("主线程执行!");
    17  }
    18}
    

    在这里说明一点,countDownLatch不可能重新初始化或者修改CountDownLatch对象内部计数器的值,一个线程调用countdown方法happen-before另外一个线程调用await方法

  2. 同步屏障CyclicBarrier

     1public static void main(String[] args) throws InterruptedException{
     2  final CyclicBarrier barrier = new CyclicBarrier(5);
     3  for(int i =0; i<5; i++){
     4    new Thread(new Runnable(){
     5      public void run(){
     6        try{
     7          Thread.sleep(1000);
     8        }catch(InterruptException e){
     9          e.printStackTrace;
    10        }
    11        System.out.println("子线程执行!");
    12        try{
    13          barrier.awiat(); // 到达屏障
    14        }catch(Exception e){
    15          e.printStrackTrace();
    16        }
    17
    18      }
    19    }).start;
    20    barrier.await(); 
    21    System.out.println("主线程执行!");
    22  }
    23}
    

countDownLatch只能使用一次,而CyclicBarrier方法可以使用reset()方法重置,所以CyclicBarrier方法可以能处理更为复杂的业务场景。

我曾经在网上看到一个关于countDownLatch和cyclicBarrier的形象比喻,就是在百米赛跑的比赛中若使用 countDownLatch的话冲过终点线一个人就给评委发送一个人的成绩,10个人比赛发送10次,如果用CyclicBarrier,则只在最后一个人冲过终点线的时候发送所有人的数据,仅仅发送一次,这就是区别。

参考链接

https://blog.csdn.net/HaHa_Sir/article/details/79521028