Semaphore是java5之后并发包里的工具类。是用来在并发时控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。例如一个奶茶店,同时只能为5个人提供服务,其余的人必须等待其前面五个人服务完毕后才能接受服务,如果所有的人同时一窝蜂的去请求服务那会导致很多问题发生甚至奶茶铺崩溃。
使用场景:
项目中某个核心接口需要频繁的访问数据库资源,频繁的io操作,如果高并发时,同时1000个线程进来同时执行大量的IO操作将会导致数据库性能大大降低甚至瘫痪,这时候我们得限制访问这个接口的并发量为1000,超过的线程等待。
构造方法:
Semaphore(int permits)
源码:
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
Semaphore(int permits)permits是信号量,即可以容纳的并发数,默认等待的线程是不公平的,即按等待的顺序依次执行。
Semaphore(int permits, boolean fair)
源码:
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
fair是指明等待的线程是否是公平的,源码可知TRUE是公平的,即等待的线程被执行的概率是相等的。
核心api:
acquire() 获得一个信号量,若此时信号量为0,则执行该方法的线程等待直到其他信息释放了信号量。
acquire(int permits) 获得permits个信号量。
release() 释放一个信号量。
release(int permits) 释放permits个信号量。
tryAcquire() 尝试获取信号量,获取成功返回true,获取失败线程不阻塞,直接返回false。
availablePermits() 返回可用的信号量。
getQueueLength() 返回等待获取信号量的线程数。
java伪代码写个某个方法只允许并发量为5的例子。
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
//初始化5个信号量
static Semaphore semaphore = new Semaphore(5,true);
static ExecutorService executor = Executors.newCachedThreadPool();
public static void main(String[] args) {
ThreadTest test = new SemaphoreTest().new ThreadTest();
//提交10个线程
for(int i=0;i<10;i++){
executor.submit(test);
}
executor.shutdown();
}
class ThreadTest implements Runnable{
//run方法只允许同时5个线程执行
public void run() {
try {
//获取信号量
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"开始执行");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName()+"执行完毕");
//释放信号量
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
执行结果: