多线程
守护线程
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 主线程等待所有子线程执行完毕再执行。
-
用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}
-
使用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}
-
等待多线程完成的
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方法
-
同步屏障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,则只在最后一个人冲过终点线的时候发送所有人的数据,仅仅发送一次,这就是区别。