概念
Semaphore是java并发包里面的一个工具类,我们限制可以访问某些资源的线程数目就可以使用Semaphore了
Semaphore:可理解为允许线程执行信号的池子,池子中放入多少个信号就允许多少线程同时执行。
Semaphore的作用:限制线程并发的数量
注意:的是 Semaphore 只是对资源并发访问的线程数进行监控,并不会保证线程安全
Semaphore使用方法
Semaphore(int permits)
创建具有给定的许可数和非公平的公平设置的 Semaphore。
permits 表示许可线程的数量
Semaphore(int permits, boolean fair)
创建具有给定的许可数和给定的公平设置的 Semaphore。
fair 表示公平性,如果这个设为 true 的话,下次执行的线程会是等待最久的线程
重要方法
release(int permits)
释放给定数目的许可,将其返回到信号量。
方法release(n) 的功能是每调用1次此方法,就动态添加n个许可
acquire()
从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
方法acquire(n) 的功能是每调用1次此方法,就消耗掉n个许可
其他方法:
方法acquireUnnterruptibly()作用是是等待进入acquire() 方法的线程不允许被中断。
方法availablePermits() 返回Semaphore对象中当前可以用的许可数。
方法drainPermits() 获取并返回所有的许可个数,并且将可用的许可重置为0
方法 getQueueLength() 的作用是取得等待的许可的线程个数
方法 hasQueueThreads() 的作用是判断有没有线程在等待这个许可
方法tryAcquire() 的作用是尝试获取1个许可。如果获取不到则返回false,通常与if语句结合使用,其具有无阻塞的特点。无阻塞的特点可以使不至于在同步处于一直持续等待的状态。
方法tryAcquire(n) 的作用是尝试获取n个许可,如果获取不到则返回false
方法tryAcquire(long timeout,TimeUnit unit)的作用是在指定的时间内尝试获取1个许可,如果获取不到则返回false
方法tryAcquire(int permits,long timeout,TimeUnit unit) 的作用是在指定的时间内尝试获取n 个许可,如果获取不到则返回false
应用场景
可用于流量控制,限制最大的并发访问数
数据库连接等
实列代码(许可2线程的数量):
//许可2线程的数量
static Semaphore semaphore = new Semaphore(2,true); // 最大线程数
public static void main(String[] args) {
for(int i=0;i<10;i++){
new Thread(new Runnable() {
@Override
public void run() {
Semaphoretest();
}
}).start();
}
}
public static void Semaphoretest(){
try {
//申请一个请求
semaphore.acquire(); // 如果线程超过设置个,其他线程会阻塞到这来,知道线程执行结束释放许可
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"进来了");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"走了");
//释放一个请求
semaphore.release();
}
}
结果
Thread-0进来了
Thread-1进来了
Thread-0走了
Thread-2进来了
Thread-1走了
Thread-3进来了
Thread-3走了
Thread-2走了
Thread-4进来了
Thread-5进来了
Thread-5走了
Thread-4走了
Thread-6进来了
Thread-7进来了
Thread-7走了
Thread-6走了
Thread-8进来了
Thread-9进来了
Thread-8走了
Thread-9走了
解释:最大并发2个线程 只有线程进行 release() 方法后才会有别的线程执行 acquire()
实列代码(许可3线程的数量):
//许可3线程的数量
static Semaphore semaphore = new Semaphore(3,true); // 最大线程数
public static void main(String[] args) {
for(int i=0;i<10;i++){
new Thread(new Runnable() {
@Override
public void run() {
Semaphoretest();
}
}).start();
}
}
public static void Semaphoretest(){
try {
//申请一个请求
semaphore.acquire(); // 如果线程超过设置个,其他线程会阻塞到这来,知道线程执行结束释放许可
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"进来了");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"走了");
//释放一个请求
semaphore.release();
}
}
结果
Thread-0进来了
Thread-1进来了
Thread-2进来了
Thread-0走了
Thread-3进来了
Thread-2走了
Thread-4进来了
Thread-1走了
Thread-5进来了
Thread-3走了
Thread-6进来了
Thread-4走了
Thread-7进来了
Thread-5走了
Thread-8进来了
Thread-6走了
Thread-7走了
Thread-8走了
Thread-9进来了
Thread-9走了
解释:最大并发3个线程 只有线程进行 release() 方法后才会有别的线程执行 acquire()