版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/d597180714/article/details/79961161
semaphore 这个类是用作访问并发控制,可以设置资源最大同时访问的个数。
初始化时参数1 permits(许可数),定义资源可以并发访问的最大个数
例如
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
Semaphore semaphore = new Semaphore(3);//资源最多可被3个线程并发访问
for(int i = 0;i < 20;i++){
final int threadnum = i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println("current thread"+Thread.currentThread().getName());
semaphore.acquire(1);//获取许可
test(threadnum);
semaphore.release(1);//释放许可
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
executorService.shutdown();//如果不shutdown工程不会结束
}
private static void test(int threadNum) throws Exception {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
System.out.println(simpleDateFormat.format(new Date())+" method run "+Thread.currentThread().getName());
Thread.sleep(1000);
}
核心方法semaphore.acquire()默认一次获取一个许可,也可以一次获取多个许可,例如semaphore.acquire(3),如果当前可获取的许可数不足,那么当前线程被阻塞。CPU调度其他线程执行。当可以获取到许可时,线程继续执行,当访问需要的资源结束时需要调用semaphore.release(),默认释放一个许可,也可以释放多个许可。如果忘记释放许可,那么当初始化定义的所有许可都被使用完后,其他线程获取不到许可都会处于阻塞状态,程序就无法继续运行。该段代码中我们对test()方法进行了访问并发控制,最大允许3个线程访问执行该方法。
运行结果如下:
可以看到test()方法确实每次只有3个线程能执行,其他的都处于阻塞状态。
Semaphore还可以定义是否公平
fair为TRUE时先阻塞的先获得锁
源码实现:
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
semaphore.tryAcquire();尝试获取一个锁,成功返回TRUE失败返回false
代码:
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
Semaphore semaphore = new Semaphore(3);//资源最多可被3个线程并发访问
for(int i = 0;i < 10;i++){
final int threadnum = i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+" running");
if(semaphore.tryAcquire()){
test(threadnum);
semaphore.release(1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
executorService.shutdown();//如果不shutdown工程不会结束
}
private static void test(int threadNum) throws Exception {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
System.out.println(simpleDateFormat.format(new Date())+" method run "+Thread.currentThread().getName());
Thread.sleep(1000);
}
运行结果:
只有3个线程执行了test()方法,其他尝试获取锁失败的线程就丢弃了
还有带参数的tryAcquire方法,第一个参数是等待的时间,第二个是等待时间的单位。
带参数时,方法会在定义的时间内一直尝试获取许可。
semaphore.tryAcquire(2,TimeUnit.SECONDS)