多线程编程中如何确保子线程执行完毕后主线程再执行-CountDownLatch

2020-10-20 00:00:00 执行 线程 后主

定义

ountDownLatch是在java1.5被引入,存在于java.util.cucurrent包下,跟它一起被引入的工具类还有CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue。

countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行,它是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

线性执行的案例

在多线程开发中,主线程数据通过子线程处理后返回的结果往往并不是我们想要的。如下面一个例子,我们的期望结果是300000,但是在主线程输出后并不是我们想要的:

		public static AtomicInteger num = new AtomicInteger(0);
	    public static void main(String []args) throws InterruptedException { 
	        //开启30个线程进行累加操作
	        for(int i=0;i<30;i++){ 
	            new Thread(){ 
	                public void run(){ 
	                    for(int j=0;j<10000;j++){ 
	                        num.incrementAndGet();//原子性的num++,通过循环CAS方式
	                    }
	                }
	            }.start();
	        }
	        System.out.println(num);
	    }

上面的这个例子中,num操作是原子的,线程安全的,输出的结果并不是我们想要的,是应为主线程输出时子线程还有没有结束。以下面的的代码来验证我们的想法:

		public static AtomicInteger num = new AtomicInteger(0);
	    public static void main(String []args) throws InterruptedException { 
	        //开启30个线程进行累加操作
	        for(int i=0;i<30;i++){ 
	            new Thread(){ 
	                public void run(){ 
	                    for(int j=0;j<10000;j++){ 
	                        num.incrementAndGet();//原子性的num++,通过循环CAS方式
	                    }
	                }
	            }.start();
	            
	        }
	        //等待计算线程执行完
	        TimeUnit.MILLISECONDS.sleep(1000);
	        System.out.println(num);
	    }

此时我们输出的结果就是300000了;这是我们在开发中已经预估到子线程的算法不会超过1000毫秒,如果在开发中不能确保估算的时间准确,或者估算的时间较长造成资源浪费怎么办?使用CountDownLatch即可解决这个问题。
《多线程编程中如何确保子线程执行完毕后主线程再执行-CountDownLatch》
上图来自JDK8的API接口文档,主要有1个构造方法5个方法。

如何改造上面的代码?

		public static AtomicInteger num = new AtomicInteger(0);
	    //使用CountDownLatch来等待计算线程执行完
	    static CountDownLatch countDownLatch = new CountDownLatch(30);
	    
	    public static void main(String []args) throws InterruptedException { 
	        //开启30个线程进行累加操作
	        for(int i=0;i<30;i++){ 
	            new Thread(){ 
	                public void run(){ 
	                    for(int j=0;j<10000;j++){ 
	                        num.incrementAndGet();//原子性的num++,通过循环CAS方式
	                    }
	                    countDownLatch.countDown();
	                }
	            }.start();
	            System.out.println("剩余数量"+countDownLatch.getCount());
	        }
	        //等待计算线程执行完
	        countDownLatch.await();
	        System.out.println(num);
	    }
    原文作者:梦里藍天
    原文地址: https://blog.csdn.net/ren365880/article/details/108007609
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。

相关文章