一、概述
Semaphore:信号量
信号量是对锁的扩展,无论是ReentrantLock或synchronized,一次都只允许一个线程访问一个临界资源,信号量可以允许多个线程同时访问一个资源。可以理解为限流的工具。
CountDownLatch:倒计时器
通常用来控制线程等待,和Object.wait()和Object.notify()有点像。它可以让某一个线程等待知道倒计时结束,再开始执行。(一个线程等待其他线程执行完成后,才能继续执行的场景)
CyclicBarrier:循环栅栏
和CountDownLatch比较类似,它可以实现线程间的计数等待,但功能跟复杂且强大。可以理解为 可以循环使用的CountDownLatch。
二、常用API及用法
Semaphore:
void acquire() 信号量获取许可证,直到得到许可,否则线程为interrupted,可以相应中断
void acquireUninterruptibly() 信号量获取许可证,直到得到许可,否则线程为interrupted,不可以相应中断
void tryAcquire() 获得许可证,如果有可用并立即返回,值为true ,将可用许可证数量减少一个。
如果没有许可证可用,那么该方法将立即返回值为false 。
boolean tryAcquire(long timeout, TimeUnit unit) 在规定的时间内获取许可,不会立即返回
**void release()**释放许可证,将其返回到信号量。
public class DemaphoreDemo implements Runnable{
private Semaphore semp = new Semaphore(5);//设置阈值
@Override
public void run() {
try {
// System.out.println(semp.availablePermits());
// semp.acquire();//获取到许可之后 -1
if (semp.tryAcquire()){
System.out.println("获取到许可。。。");
Thread.sleep(2000);
}else{
System.out.println("获取失败");
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
semp.release();//释放后 +1
}
}
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(20,30,0,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
DemaphoreDemo demo = new DemaphoreDemo();
for (int i = 0; i < 20; i++){
pool.submit(demo);//用线程池执行多线程
}
pool.shutdown();
}
}
CountDownLatch:
void await() 如果当前计数为零,则此方法立即返回。 如果当前计数大于零,则当前线程将被禁用以进行线程调度,是阻塞线程,一直等 直到计数为0
boolead await(long timeout, TimeUnit unit) 在规定的时间内等待
void countDown() 计数 -1
long getCount() 获取当前计数
public class CountDownLatchDemo implements Runnable{
private static CountDownLatch cdl = new CountDownLatch(10);//设置阈值
private volatile AtomicInteger i = new AtomicInteger(0);
@Override
public void run() {
try {
Thread.sleep(i.get()*1000);
System.out.println("线程"+ i.incrementAndGet() +"执行完成,等待其他线程");
cdl.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(20,30,0,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
CountDownLatchDemo demo = new CountDownLatchDemo();
for (int i = 0; i < 10; i++){
pool.submit(demo);
}
try {
cdl.await();
System.out.println("所有线程执行完毕!!!!!");
} catch (InterruptedException e) {
e.printStackTrace();
}
pool.shutdown();
}
}
CyclicBarrier: