java.util.concurrent.Semaphore所提供的功能和synchronized所提供的功能是一致的,但Semaphore可以说是synchronized的一个升级版。Semaphore可以控制线程的并发数量,而单纯synchronized是无法做到的。
看如下代码:
public class Service{
//Semaphore.Semaphore(int permits)
public Semaphore semaphore = new Semaphore(1);
public void testService() throws InterruptedException{
semaphore.acquire();
System.out.println(Thread.currentThread().getName() +" "+ "begin");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() +" " + "end");
semaphore.release();
}
}
Semaphore(int permits);构造器
permits参数:在同一时间,最多可同时执行semaphore.acquire(),semaphore.release()之间的代码的线程个数。构造方法中的perimit并不是最终可同时执行许可数量,只是初始数量,acquire()方法每执行一次,可同时执行的线程数-1,release()方法每执行一次可执行线程数+1。当没有执行代码块的资格时,则等待。其实acquire()本质就是减法操作,release()是加法操作,我们当然可以-1个+2个,也就是调用1次acquire(),2次release(),此时代码块可同时执行线程数量则比初始化时多了一个。当然acquire和release方法也可以增加一个int参数,表示使用或释放多个许可。
public class TestSemaphore {
public static void main(String[] args) {
Service service = new Service();
Thread t = new ThreadTest(service);
t.setName("A");
Thread t2 = new ThreadTest(service);
t2.setName("B");
Thread t3 = new ThreadTest(service);
t3.setName("C");
t.start();
t2.start();
t3.start();
}
}
class ThreadTest extends Thread{
Service service;
public ThreadTest(Service service){
this.service = service;
}
@Override
public void run() {
try {
service.testService();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
调用结果如下:
A begin
A end
B begin
B end
C begin
C end
上面设置的最多允许执行acquire()和release()之间代码块的线程数为1,也就是串行执行,实现了线程同步。
当Semaphore(int permits)中permits设置为2时,如下:
B begin
A begin
A end
B end
C begin
C end
可以发现BC线程同时进入了代码块。
其他的一些方法:
int availablePermits()返回当前可用许可数
int drainPermits()返回当前许可数后将其置为0
int getQueueLength()获取等待许可的线程个数
boolean hasQueuedThreads()当前是否有等待的线程