一,简介
Semaphore 允许一定数量线程同时访问临界区资源。
二,构造函数
在构造信号量对象时,须指定信号量的准入数,即同时能申请多少个许可。当每个线程每次只能申请一个许可时,就相当于指定了同时有多少个线程可以访问某一资源。
/**
* Creates a {@code Semaphore} with the given number of
* permits and nonfair fairness setting.
*
* @param permits the initial number of permits available.
* This value may be negative, in which case releases
* must occur before any acquires will be granted.
*/
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
/**
* Creates a {@code Semaphore} with the given number of
* permits and the given fairness setting.
*
* @param permits the initial number of permits available.
* This value may be negative, in which case releases
* must occur before any acquires will be granted.
* @param fair {@code true} if this semaphore will guarantee
* first-in first-out granting of permits under contention,
* else {@code false}
*/
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
三,主要方法
acquire()
方法尝试获得一个准入的许可。若无法获得,则线程会等待,直到有线程释放一个许可或者当前线程被中断。
acquireUninterruptibly()
方法和 acquire 方法类似,但是不响应中断。
tryAcquire()
尝试获得一个许可,如果成功返回 true,失败则返回 false,它不会进行等待,立即返回。
release()
用于在线程访问资源结束后,释放一个许可,以使其他等待许可的线程可以进行资源访问。
四,简单使用
import cn.hutool.core.date.DateUtil;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreDemo implements Runnable {
//创建信号量实例,指定准入数为5
final Semaphore semp = new Semaphore(5);
@Override
public void run() {
try {
//获取许可,若得到许可再继续执行
semp.acquire();
//模拟耗时操作
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + ":done!" + DateUtil.formatDateTime(new Date()));
//释放许可
semp.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(20);
final SemaphoreDemo demo = new SemaphoreDemo();
for (int i = 0; i < 20; i++) {
exec.submit(demo);
}
exec.shutdown();
}
}
结果打印:
pool-1-thread-2:done!2021-05-12 11:58:45
pool-1-thread-1:done!2021-05-12 11:58:45
pool-1-thread-5:done!2021-05-12 11:58:45
pool-1-thread-9:done!2021-05-12 11:58:45
pool-1-thread-13:done!2021-05-12 11:58:45
pool-1-thread-17:done!2021-05-12 11:58:47
pool-1-thread-6:done!2021-05-12 11:58:47
pool-1-thread-14:done!2021-05-12 11:58:47
pool-1-thread-18:done!2021-05-12 11:58:47
pool-1-thread-10:done!2021-05-12 11:58:47
pool-1-thread-7:done!2021-05-12 11:58:49
pool-1-thread-3:done!2021-05-12 11:58:49
pool-1-thread-11:done!2021-05-12 11:58:49
pool-1-thread-15:done!2021-05-12 11:58:49
pool-1-thread-19:done!2021-05-12 11:58:49
pool-1-thread-12:done!2021-05-12 11:58:51
pool-1-thread-4:done!2021-05-12 11:58:51
pool-1-thread-8:done!2021-05-12 11:58:51
pool-1-thread-16:done!2021-05-12 11:58:51
pool-1-thread-20:done!2021-05-12 11:58:51
可以看到,最多有5个线程同时打印。
评论区