Java CountDownLatch|CyclicBarrier|Semaphore

CountDownLatch

CountDownLatch 是在 java 1.5 被引入。

CountDownLatch 是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程执行完后再执行。

CountDownLatch 主要有两个方法,当一个或多个线程调用 await 方法时,调用线程会被阻塞。其他线程调用countDown 方法计数器减1 (调用 countDown 方法时线程不会阻塞),当计数器的值变为 0 ,因调用 await 方法被阻塞的线程会被唤醒继续执行。

示例

假如教室里面有三个学生在上自习,三个人走了以后班长才能走然后把门关上。

enum Man{
	ONE(1,"张三"),TWO(2,"李四"),TREEE(3,"王五");
	
	private int index;
	private String name;
	public int getIndex() {
		return index;
	}
	public String getName() {
		return name;
	}
	private Man(int index, String name) {
		this.index = index;
		this.name = name;
	}
	public static Man getIndex(int index) {
		Man[] mans = Man.values();
		for(Man m : mans) {
			if(m.getIndex() == index) {
				return m;
			}
		}
		return null;
	}
}

public class CountDownLatchDemo {
	public static void main(String[] args) {
		for (int i = 1; i <=3; i++) {
			new Thread(()->{
				System.out.println(Thread.currentThread().getName()+" 离开教室...");
			},Man.getIndex(i).getName()).start(); 
		}
		System.out.println(Thread.currentThread().getName()+"最后离开教室关门...");
	}
}

运行结果

发现结果并不是我们想象中的那样,于是开始加上锁机制。

改进代码

// 枚举类不变,主方法加锁
public class CountDownLatchDemo {
	public static final int COUNT = 3;
	public static void main(String[] args) throws InterruptedException {
		// 上锁
		CountDownLatch cdl = new CountDownLatch(COUNT);
		
		for (int i = 1; i <=3; i++) {
			new Thread(()->{
				System.out.println(Thread.currentThread().getName()+" 离开教室...");
				cdl.countDown();	// 数字-1
			},Man.getIndex(i).getName()).start(); 
		}
		cdl.await(); // 等待,数字变为 0 时自动唤醒
		System.out.println(Thread.currentThread().getName()+"最后离开教室关门...");
	}
}

运行结果

CyclicBarrier

CyclicBarrier 是在 java 1.5 被引入。

其字面意思是循环栅栏,CyclicBarrier的字面意思是可循环(Cyclic)使用的屏障(barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过 CyclicBarrier 的 await() 方法。

示例

public class CyclicBarrierDemo {
	public static final int COUNT = 3;
	public static void main(String[] args) throws InterruptedException {
		CyclicBarrier cb = new CyclicBarrier(3,()->{
			System.out.println("班长最后离开教室关门...");
		}); 
		
		for (int i = 1; i <=3; i++) {
			new Thread(()->{
				System.out.println(Thread.currentThread().getName()+" 离开教室...");
				try {
					cb.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (BrokenBarrierException e) {
					e.printStackTrace();
				}
			},Man.getIndex(i).getName()).start(); 
		}
	}
}

运行结果

Semaphore

这个类大家一看都应该知道,是信号量的意思。在多线程编程中,特别是秒杀系统被广泛使用,他可以实现多个线程抢占多份资源安全的功能。

信号量的主要用户两个目的,一个是用于多喝共享资源的相互排斥使用,另一个用于并发资源数的控制。

扫描二维码关注公众号,回复: 10436457 查看本文章

示例

import java.util.concurrent.Semaphore;

/* 模拟6辆车抢三个停车位 */
public class SemaphoreDemo {
	public static void main(String[] args) {
		// 三个停车位
		Semaphore semaphore = new Semaphore(3);
		for (int i = 1; i <= 6; i++) {
			new Thread(()->{
				try {
					// 抢资源
					semaphore.acquire();
					System.out.println(Thread.currentThread().getName()+" 抢到车位");
					Thread.sleep(3000);
					System.out.println(Thread.currentThread().getName()+" 3秒后离开");
					// 放弃资源
					semaphore.release();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
			},String.valueOf(i)).start();; 
		}
	}
}

运行结果

发布了80 篇原创文章 · 获赞 55 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/cong____cong/article/details/104454605