介绍
Semaphore是Java提供的另一种锁机制,称为信号量,它可允许指定数量的多个线程同时拥有一个信号量。区别于锁的关键在于,锁是为了保证资源的安全而设计的,而信号量是为了限制资源的并发数,对性能进行考虑而设计。
设计原理
它通过维护一个计数器来限制访问的线程的数量,若增加一个线程的访问时,信号量减一,直到信号量为0时,则无法加入新的访问的线程,这些线程将等待信号量的增加,如大于0,则等待的线程即可资源进行访问。例如,当有信号量总额为5时,10个线程并发访问某个资源,当有5个线程访问的时候,信号量为0,当有线程释放信号量时,等待的线程即可执行。
代码实现
核心API:
构造函数:
public Semaphore(int permits); //信号量个数
public Semaphore(int permits,boolean fair); //第二个参数为是否公平
主要的逻辑方法:
public void acquire(); //获取信号量,获取信号量,获取不到则到等待区等待
public void acquireUniterruptibly(); //不支持中断的获取信号量
public boolean tryAcquire(); //尝试获取信号量,类似tryLock();
public boolean tryAcquire(long timeout,TimeUnit unit); //尝试获取信号量,获取不到则进行等待的时间
public void release(); //释放信号量
例子:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(20);
Semaphore semp = new Semaphore(5);
for (int i = 0;i<20;i++){
exec.submit(new MyTask(semp));
}
exec.shutdown();
}
private static class MyTask implements Runnable{
private Semaphore semaphore;
public MyTask(Semaphore semaphore){
this.semaphore = semaphore;
}
@Override
public void run() {
try {
semaphore.acquire();
Thread.sleep(2000); //模拟2S的线程操作
System.out.println(System.currentTimeMillis() + ":done!");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}