信号量(Semaphore)
信号量是限制并发线程数的一种方法,广义上,信号量是对锁的扩展。不同于synchronized和ReentrantLock,synchronized和ReentrantLock限制单次只允许一个线程访问一个资源,而信号量则可以指定单次有多少个线程访问一个资源。
Semaphore提供两个构造器:
public Semaphore(int permits);
public Semaphore(int permits,boolean fair)
// fair可以指定是否公平
主要包含如下方法:
public void acquire();
public void acquireUninterruptibly()
public boolean tryAcquire()
public boolean tryAcquire(long timeout,TimeUnit unit)
public void release();
acquire();
尝试获得一个准入许可,若无法获得,则线程会等待,直到有线程释放一个许可或当前线程被中断。
acquireUninterruptibly()
效果和acquire类似,但是不响应线程中断
tryAcquire()
尝试获得一个许可,如果成功返回true,失败返回false。不会等待,立即返回(可以通过传入timeout和unit设置等待时间,unit为时间单位)
release()
当线程获得许可进入资源并处理完后,需要通过调用release方法释放许可,以便让其他等待进入许可的线程可以获取许可并访问资源。
简单的demo如下
package com.cn.demo.semp;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SempDemo implements Runnable {
// 以公平方式允许五个线程同时访问指定资源
final Semaphore semp = new Semaphore(5, true);
@Override
public void run() {
try {
semp.acquire();
// 模拟耗时的业务逻辑
Thread.sleep(5000);
System.out.println("线程" + Thread.currentThread().getName() + "执行完毕!");
semp.release();
} catch (InterruptedException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(10);
final SempDemo sempDemo = new SempDemo();
for (int i = 0; i < 20; i++) {
executor.execute(sempDemo);
}
}
}