Java项目实践,CountDownLatch实现多线程闭锁

2021-01-06 00:03:44 浏览数 (1)

摘要

本文主要介绍Java多线程并发中闭锁(Latch)的基本概念、原理、实例代码、应用场景,通过学习,可以掌握多线程并发时闭锁(Latch)的使用方法。

概念

“闭锁”就是指一个被锁住了的门将线程a挡在了门外(等待执行),只有当门打开后(其他线程执行完毕),门上的锁才会被打开,a才能够继续执行。

闭锁(Latch),目的是使多个线程在完成各自任务后,才会打开继续执行后面的任务,否则一直等待。

计数器闭锁(CountDownLatch)是一个同步工具类, 可以用来协调多个线程的执行时间,允许一个或多个线程等待某个事件的发生。

CountDownLatch有个正数的计数器,countDown(); 对计数器做减法操作,await(); 等待计数器等于0。所有await的线程都会阻塞,直到计数器为0或者等待线程中断或者超时。

例如, 可以让a线程在其他线程运行完毕后再执行。如果其他线程没有执行完毕,则a线程就会一直等待。

原理分析

CountDownLatch的实现原理:

1、CountDownLatch在创建时, 会指定一个计数器,表示等待线程的执行数量(比如,3就表示当3个线程执行完毕后,再结束闭锁,使a能够继续执行);

2、 其他每个线程在各自执行完毕时, 分别调用一次countDown())方法,用来递减计数器, 表示有一个线程已经执行完毕了;这时, 线程a可以调用await()方法, 用来等待计数器的值为0。

3、如果计数器的值大于0, 那么await()方法会一直阻塞, 直到计数器为0时,线程a才会继续执行;

4、如果线程a一直无法等到计数器为0,则会显示等待超时,当然也可以在线程a等待时,通过程序中断等待。

实例代码

在Java中, 可以使用CountDownLatch实现多线程闭锁,具体实现代码如下:

代码语言:javascript复制
package com.javalearns.juc;

import java.util.concurrent.CountDownLatch;

public class JavaLearnsCountDownLatch {
	public static void main(String[] args) {
	    //计数器为8
		CountDownLatch countDownLatch = new CountDownLatch(8);
      //将CountDownLatch对象传递到线程的run()方法中,当每个线程执行完毕run()后就将计数器减1
        MyThread myThread = new MyThread(countDownLatch);
        long start = System.currentTimeMillis();
        //创建8个线程,并执行
		for (int i = 0; i <8; i  ) {
			new Thread(myThread).start();
		}
		try {
			//主线程(main)等待:等待的计数器为0;即当CountDownLatch中的计数器为0时,Main线程才会继续执行。
			countDownLatch.await();
		} catch (InterruptedException e) {
		    e.printStackTrace();
		}
		long end = System.currentTimeMillis();
		System.out.println("耗时:"   (end - start));
	}
}
class MyThread implements Runnable {
	private CountDownLatch latch;
	public MyThread(CountDownLatch latch) {
		this.latch = latch;
	}
	@Override
	public void run() {
		try {
			Thread.sleep(5000);
		}catch (InterruptedException e){
		    e.printStackTrace();
        }
            finally {
			latch.countDown();//每个子线程执行完毕后,触发一次countDown(),即计数器减1
		}
	}
}

应用场景

1、确保某个计算,在其需要的所有资源都准备就绪后再执行,比如:要计算某个工程材料的合价,要知道材料的单价和工程量后,才能执行材料合价计算。

2、确保某个服务,在其依赖的所有其他服务都已经启动后再启动。

3、确保某个任务,在所有参与者都准备就绪后再执行,比如:线上上课,在全班30个同学都全部上线后,老师才能开始上课。

0 人点赞