当我们创建一个可扩展大小的线程池,并且需要在线程池内同时让有限数目的线程并发运行时,就需要用到Semaphore(信号灯机制),Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目,它是一个计数信号量,从概念上讲,信号量维护了一个许可集合,如有必要,在许可可用前会阻塞每一个acquire(),然后再获取该许可,每个release() 添加一个许可,从而可能释放一个正在阻塞的获取者。
代码如下:
package com.qimh.concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemahoreDemo {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final Semaphore sp = new Semaphore(3);//定义有3个信号灯
for(int i=0;i<5;i++){
Runnable runnable = new Runnable(){
public void run(){
System.out.println("线程" + Thread.currentThread().getName() +" " + System.currentTimeMillis());
try {
sp.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
//sp.availablePermits()指的是当前信号灯库中有多少个可以被使用
System.out.println("线程" + Thread.currentThread().getName() +
"进入,当前已有" + (3-sp.availablePermits()) + "个并发" + "---"+sp.availablePermits() + " " +System.currentTimeMillis()); //3-sp.availablePermits()就代表了当前有多少个线程在并发运行
try {
Thread.sleep((long)(Math.random()*10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"即将离开");
sp.release();
//下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
System.out.println("线程" + Thread.currentThread().getName() +
"已离开,当前已有" + (3-sp.availablePermits()) + "个并发");
}
};
service.execute(runnable);
}
service.shutdown();
}
}
代码解析:
该例子定义了一个newCachedThreadPool,在该Pool中利用for循环同时创建5个线程,现在通过Semaphore,创建一个只允许在线程池中有3个线程并发运行,sp.acquire()表示某个线程获得了一个信号灯,开始运行,在运行结束时,通过sp.release()还回这个信号灯,以便剩下的线程获得信号灯运行,sp.availablePermits()指的是当前信号灯库中有多少个可以被使用,由于例子中定义有3个信号灯,所以3-sp.availablePermits()就代表了当前有多少个线程在并发运行,上例运行结果如下:
线程pool-1-thread-1 1522397840180
线程pool-1-thread-1进入,当前已有1个并发---2 1522397840181
线程pool-1-thread-4 1522397840181
线程pool-1-thread-4进入,当前已有2个并发---1 1522397840181
线程pool-1-thread-3 1522397840181
线程pool-1-thread-3进入,当前已有3个并发---0 1522397840181
线程pool-1-thread-2 1522397840180
线程pool-1-thread-5 1522397840181
线程pool-1-thread-4即将离开
线程pool-1-thread-4已离开,当前已有2个并发
线程pool-1-thread-2进入,当前已有3个并发---0 1522397841645
线程pool-1-thread-1即将离开
线程pool-1-thread-1已离开,当前已有2个并发
线程pool-1-thread-5进入,当前已有3个并发---0 1522397845323
线程pool-1-thread-2即将离开
线程pool-1-thread-2已离开,当前已有2个并发
线程pool-1-thread-3即将离开
线程pool-1-thread-3已离开,当前已有1个并发
线程pool-1-thread-5即将离开
线程pool-1-thread-5已离开,当前已有0个并发
参考链接:https://blog.csdn.net/zzp_403184692/article/details/8017173