J.U.C AQS(abstractqueuedssynchronizer--同步器)
同步器是用来构建锁和其他同步组件的基础框架,它的实现主要依赖一个int成员变量来表示同步状态以及通过一个FIFO队列构成等待队列。
CountDownLatch
用来控制一个线程等待多个线程。维护了一个计数器cnt,每次调用countDown()方法,会是cnt的计数值减1,减到0 的时候,那些因为调用await()而等待的线程被唤醒。
package ConcurrentExemple;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchExemple {
public static void main (String[]args)throws InterruptedException{
final int totalThread=10;
CountDownLatch countDownLatch=new CountDownLatch(totalThread);
ExecutorService executorService= Executors.newCachedThreadPool();
for(int i=0;i<10;i++){
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"开始运行");
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"已经运行完");
countDownLatch.countDown();
});
}
countDownLatch.await();
System.out.println("休眠线程唤醒");
executorService.shutdown();
}
}
CyclicBarrier
用来控制多个线程相互等待,等到所有的线程都到达时,这些线程才会继续执行。
它同CountDownLatch一样维护一个计数器cnt,每个线程调用一次await(),cnt减一,当cnt为0 的时候,所有的线程都到达,这时这些线程继续执行。CyclicBarrier 和 CountdownLatch 的一个区别是,CyclicBarrier 的计数器通过调用 reset() 方法可以循环使用,所以它才叫做循环屏障。
package ConcurrentExemple;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicBarrierExemple {
public static void main(String[]args){
final int totalThread=10;
CyclicBarrier cyclicBarrier=new CyclicBarrier(totalThread);
ExecutorService executorService= Executors.newCachedThreadPool();
for(int i=0;i<totalThread;i++){
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"begin");
try{
cyclicBarrier.await();
}catch (InterruptedException| BrokenBarrierException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"end");
});
}
executorService.shutdown();
}
}
Semaphore
信号量Semaphore 类似于操作系统中的信号量,可以控制对互斥资源的访问线程数。
以下代码模拟了对某个服务的并发请求,每次只能有 3 个客户端同时访问,请求总数为 10。
package ConcurrentExemple;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreExemple {
public static void main(String[]args){
int customer=3;
int totalThread=10;
Semaphore semaphore=new Semaphore(customer);
ExecutorService executorService= Executors.newCachedThreadPool();
for(int i=0;i<totalThread;i++){
executorService.execute(()->{
try {
semaphore.acquire();
System.out.println(semaphore.availablePermits()+" ");
Thread.sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}finally {
semaphore.release();
}
});
}
executorService.shutdown();
}
}