文章目录
一、并发容器
CountDownLatch
CountDownLatch它可以实现类似计数器的功能,当前线程需要等待其他任务执行完成才开始执行。
/**
* 构造函数初始化计数的数量,需要等待执行的任务个数
*/
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
/**
* 任务执行完毕之后,减去1,当等待任务为0时,唤醒其他线程。
*/
public void countDown() {
sync.releaseShared(1);
}
/**
* 当前线程等到线程的计数器为0时候开始继续执行。
*/
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
示例
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"执行开始....");
try {
Thread.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+"执行结束....");
latch.countDown();
},"t1").start();
System.out.println("等待t1线程执行完毕...");
latch.await();
System.out.println("t1线程已经执行完毕");
System.out.println("继续执行主线程");
}
}
注释掉latch.await(),输出
等待t1线程执行完毕...
t1线程已经执行完毕
继续执行主线程
t1执行开始....
t1执行结束....
加上latch.await(),输出
等待t1线程执行完毕...
t1执行开始....
t1执行结束....
t1线程已经执行完毕
继续执行主线程
CyclicBarrier (回环栅栏)
CyclicBarrier它的作用就是会让所有线程都等待完成后才会继续下一步行
动。
构造器
/**
CyclicBarrier初始化时规定一个数目,
然后计算调用了CyclicBarrier.await()进入等待的线程数。
当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。
*/
public CyclicBarrier(int parties) {
this(parties, null);
}
CyclicBarrier 中最重要的方法就是await 方法:
/**
用来挂起当前线程,直至所有线程都到达barrier 状态再同时执行后续任
务;
*/
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
示例
public class CyclicBarrierDemo {
public static void main(String[] args) {
//模拟5个人聚会,先后时间到达,人员到齐之后才可以进行活动
int N =5;
CyclicBarrier barrier = new CyclicBarrier(N);
for(int i=1;i<=N;i++) {
new Person("person" + i, barrier).start();
}
}
static class Person extends Thread {
private CyclicBarrier cyclicBarrier;
public Person(String personname,CyclicBarrier cyclicBarrier) {
super(personname);
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
Thread.sleep(3);
System.out.println("人员" + Thread.currentThread().getName() + " 到,等待其他人到场");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("所有人到齐,可以进行其他活动");
}
}
}
人员person1 到,等待其他人到场
人员person3 到,等待其他人到场
人员person4 到,等待其他人到场
人员person2 到,等待其他人到场
人员person5 到,等待其他人到场
所有人到齐,可以进行其他活动
所有人到齐,可以进行其他活动
所有人到齐,可以进行其他活动
所有人到齐,可以进行其他活动
所有人到齐,可以进行其他活动
Semaphore (信号量)
Semaphore 可以控制同时访问的线程个数,通过acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。
示例
public class SemaphoreDemo {
public static void main(String[] args) {
int N = 5; //购票场景,5个人需要购买票,人工窗口只有2个
Semaphore semaphore = new Semaphore(2); //人工窗口
for(int i=1;i<=N;i++)
new BuyTicketor(i,semaphore).start();
}
static class BuyTicketor extends Thread{
private int num;
private Semaphore semaphore;
public BuyTicketor(int num,Semaphore semaphore){
this.num = num;
this.semaphore = semaphore;
}
@Override
public void run() {
try {
semaphore.acquire();
System.out.println("购买者"+this.num+"购买票中...");
Thread.sleep(3);
System.out.println("购买者"+this.num+"购买完成...");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出
购买者1购买票中...
购买者2购买票中...
购买者2购买完成...
购买者1购买完成...
购买者3购买票中...
购买者4购买票中...
购买者4购买完成...
购买者3购买完成...
购买者5购买票中...
购买者5购买完成...