以前写过关于线程同步辅助类: CountDownLatch和CyclicBarrier,本次介绍写另一个线程同步辅助类:Semaphore。
简介
信号量(semaphore)是在多线程环境下负责协调各个线程,正确合理的使用公用资源。Semaphore是基于计数的信号量。它可以设定一个阈值,多个线程竞争获取许可信号,做完自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制。
API
创建信号量
Semaphore(int permits)
参数permits(许可)指定了同时可以多少个线程访问公共资源。
若设置1,则可用于线程间同步
若设置>1,则可用于限流等
阻塞获取信号量
acquire()
释放信号量
release()
使用场景
常用于仅能提供有限访问的资源,如数据库链接数最大只有20, 而上层应用并发数远大于20,如果同时对数据库进行操作,则就会出现因无法获取数据库连接数而导致的异常。此时就可以通过该信号量来做并发访问限制。
实际案例
@org.junit.Test
public void test() throws InterruptedException {
AtomicInteger index = new AtomicInteger();
//执行线程池
Executor executor = Executors.newFixedThreadPool(10);
//初始化信号量
Semaphore semaphore = new Semaphore(4);
//任务执行完成信号
CountDownLatch countDownLatch = new CountDownLatch(10);
//执行任务
for (int i = 0; i < 10; i++) {
executor.execute(new Task(semaphore, countDownLatch));
}
countDownLatch.await();
System.out.println(simpleDateFormat.format(new Date())+"==============全部执行完成!");
}
private class Task implements Runnable{
private Semaphore semaphore;
private CountDownLatch countDownLatch;
Task(Semaphore semaphore, CountDownLatch countDownLatch){
this.semaphore = semaphore;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
//获取许可
semaphore.acquire();
System.out.println(simpleDateFormat.format(new Date())+" "+Thread.currentThread().getName() + ": 执行中");
Thread.sleep(2000);
} catch (InterruptedException e) {
} finally {
//释放许可
semaphore.release();
//任务执行标示
countDownLatch.countDown();
}
}
}