countDownLatch:
countDownLatch可以实现等待指定数量的线程执行完毕后在执行此线程
实现原理: 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
实例:等待三个学员都准备完毕后,教练才开始训练(三个学员线程都运行到一个位置后,执行教练线程)
/***
* 等待三个学员准备完毕后,教练开始训练
*/
private CountDownLatch countDownLatch = new CountDownLatch(3);
public void Athlete(){
System.out.println(Thread.currentThread().getName()+"准备完毕");
countDownLatch.countDown(); //线程数减一 减到0就会唤醒等待其他线程执行的线程
}
public void coach(){
try {
countDownLatch.await(); //等待其他线程执行后在执行方法
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"准备训练");
}
public static void main(String[] args) {
Athletes athletes = new Athletes();
new Thread(new Runnable() {
@Override
public void run() {
athletes.coach();
}
},"教练").start();
new Thread(new Runnable() {
@Override
public void run() {
athletes.Athlete();
}
},"刘翔").start();
new Thread(new Runnable() {
@Override
public void run() {
athletes.Athlete();
}
},"姚明").start();
new Thread(new Runnable() {
@Override
public void run() {
athletes.Athlete();
}
},"孙杨").start();
new Thread(new Runnable() {
@Override
public void run() {
athletes.Athlete();
}
},"哈哈").start();
}
//执行结果
刘翔准备完毕
姚明准备完毕
哈哈准备完毕
教练准备训练
孙杨准备完毕
CyclicBarrier
CyclicBarrier可以实现等待所有线程都准备好之后,再一起执行
实现原理:计数器递增,提供reset功能,可以多次使用实现原理:计数器递增,提供reset功能,可以多次使用
实例:所有运动员准备好之后,一起出发(等待所有线程都运行到这个位置后,再同时执行)
/***
* 三个运动员准备后 同时出发
*/
public class CyclicBarrierDemo {
CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
public void demo(){
try {
System.out.println(Thread.currentThread().getName()+"正在准备");
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName()+"出发");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
CyclicBarrierDemo cyclicBarrierDemo = new CyclicBarrierDemo();
new Thread(new Runnable() {
@Override
public void run() {
cyclicBarrierDemo.demo();
}
},"运动员一").start();
new Thread(new Runnable() {
@Override
public void run() {
cyclicBarrierDemo.demo();
}
},"运动员二").start();
new Thread(new Runnable() {
@Override
public void run() {
cyclicBarrierDemo.demo();
}
},"运动员三").start();
}
}
//执行结果
运动员一正在准备
运动员二正在准备
运动员三正在准备
运动员三出发
运动员一出发
运动员二出发
Semaphore
信号量:
Semaphore 是 synchronized 的加强版,作用是控制线程的并发数量。
Semaphore(int permits):构造方法,创建具有给定许可数的计数信号量并设置为非公平信号量。
Semaphore类所提供的的方法(红色为重要常用方法)
- Semaphore(int permits,boolean fair):构造方法,当fair等于true时,创建具有给定许可数的计数信号量并设置为公平信号量。
- void acquire():从此信号量获取一个许可前线程将一直阻塞。相当于一辆车占了一个车位。
- void acquire(int n):从此信号量获取给定数目许可,在提供这些许可前一直将线程阻塞。比如n=2,就相当于一辆车占了两个车位。
- void release():释放一个许可,将其返回给信号量。就如同车开走返回一个车位。
- void release(int n):释放n个许可。
- int availablePermits():当前可用的许可数。
实例:十个工人要使用三台机器进行一些工作(十个工人为十个线程,三台机器为三个资源,每次最多只能有三个线程获得资源并执行代码)
/***
* 模拟 10个工人 使用 三台机器
*/
public class SemaphoreDemo implements Runnable{
private int pope; //工人数 工人工号
private Semaphore semaphore; //机器数量
public SemaphoreDemo(int pope, Semaphore semaphore) {
this.pope = pope;
this.semaphore = semaphore;
}
@Override
public void run() {
try {
semaphore.acquire(); //获取资源
System.out.println(Thread.currentThread().getName()+"正在使用机器进行工作");
semaphore.release(); //释放资源
System.out.println(Thread.currentThread().getName()+"使用完毕,释放资源");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
SemaphoreDemo semaphoreDemo = new SemaphoreDemo(10,semaphore);
for(int i = 1 ; i<=10 ;i++ ){
new Thread(semaphoreDemo,"员工"+i).start();
}
}
//执行结果
员工2正在使用机器进行工作
员工1正在使用机器进行工作
员工2使用完毕,释放资源
员工1使用完毕,释放资源
员工3正在使用机器进行工作
员工3使用完毕,释放资源
员工4正在使用机器进行工作
员工4使用完毕,释放资源
员工5正在使用机器进行工作
员工5使用完毕,释放资源
员工6正在使用机器进行工作
员工6使用完毕,释放资源
员工7正在使用机器进行工作
员工7使用完毕,释放资源
员工8正在使用机器进行工作
员工8使用完毕,释放资源
员工9正在使用机器进行工作
员工9使用完毕,释放资源
员工10正在使用机器进行工作
员工10使用完毕,释放资源