AQS应用-CountDownLatch

生活

代码无非是生活现实场景的翻译,把某些场景翻译成代码,即简单又复杂。
AQS中的应用也与我们的生活息息相关。

场景

今天来看一个有趣的场景,经历过学生时代的,都对那段必须跑的长跑深恶痛绝,发令枪响开跑,然后等到所有人跑完,老师才会把大家召集起来统一公布成绩。
这个场景用程序来模拟,实际就是N个线程执行操作,等全部执行完了,才执行某一个特定操作。
countDownLatch正是一个能提供如此功能的并发工具类了。

简述

CountDownLatch是JDK1.5中引入进来的,称之为闭锁,或者同步计数器等。
下面的代码告诉你如何创建一个资源数为N的闭锁。(即学生数为N的闭锁)


//此为创建闭锁的构造器
 public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

注意资源数不能小于0


//此为创建闭锁的代码
//就是new对象,没啥好说的,具体this.sync=new Sync(count) 就不说了可以自己点进去看,其实归根到底还是到AQS的共享资源state
CountDownLatch latch = new CountDownLatch(5);

闭锁中使用到的两个方法如下:
计数器-1:

public void countDown() {
        sync.releaseShared(1);
    }

等待:

public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

这个代码很简单,不明白的可以看下前面的AQS初探,借用了前辈写的东西,一步步走下去,还是很详细的哦。

案例

下面贴出使用的案例代码

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class CDLTest {
	
	public static void main(String[] args) {
		CountDownLatch latch = new CountDownLatch(5);
		Thread t1 = new Thread(new Student(latch, "A"));
		Thread t2 = new Thread(new Student(latch, "B"));
		Thread t3 = new Thread(new Student(latch, "C"));
		Thread t4 = new Thread(new Student(latch, "D"));
		Thread t5 = new Thread(new Student(latch, "E"));
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		
		try {
		//等待 计数器减为0才往下走
			latch.await();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("开始公布成绩。。。。。。。。。。。");
		for(int i=0;i<Student.students.size();i++) {
			System.out.println("第"+(i+1)+"名:"+Student.students.get(i).getName());
		}

	}
	
	static class Student implements Runnable{
		
		private CountDownLatch latch;
		private String name;
		public static final List<Student> students = new ArrayList<>();

		@Override
		public void run() {
			try {
				Thread.sleep(Long.valueOf(new Random().nextInt(2000)));
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("学生:"+name+",跑到终点!");
			students.add(this);
			//计数器-1
			latch.countDown();
			
		}

		public String getName() {
			return name;
		}

		public Student(CountDownLatch latch, String name) {
			super();
			this.latch = latch;
			this.name = name;
		}
		
	
		
		
	}

}

执行得到的一次结果如下:
学生:A,跑到终点!
学生:C,跑到终点!
学生:D,跑到终点!
学生:B,跑到终点!
学生:E,跑到终点!
开始公布成绩。。。。。。。。。。。
第1名:A
第2名:C
第3名:D
第4名:B
第5名:E

注意

注意闭锁是没法重用的,用过以后这个对象就木有用了,因为没有提供对外的方法来重置AQS中的state。

后记

代码很简单,思想很牛逼,前辈写的代码要多多学习啊,哈哈,今天到这里,明天看看后面的回环栅栏。~~

猜你喜欢

转载自blog.csdn.net/qq_28605513/article/details/84261940