java中信号灯可以控制多个线程同时访问同一个资源的操作数量,注意这句话的重点在于“控制”二字。即可以为某种容器施加边界限制,也可以实现对某种资源的池化,比如线程池中限制最大运行5个线程,当有有超过5个线程同时来访问线程池的时候,必定有一个线程会处于阻塞等待状态。通过控制边界数量,可以避免过度线程占用内存而引发内存不足问题。其实现是通过一组运行在有界容器内的访问许可permit。
比如商场的车库,车位有限,但是要在这里停车的数量大于车位,就必须有部分车辆要等待车库里面的车先开出来,在此期间将一直处于阻塞。且看下面代码。
import java.util.concurrent.Semaphore;
/**
*
* @author Jerry
* @date 2017/12/24 0024
*/
public class Garage {
public static void main(String[] args) {
Semaphore semaphore=new Semaphore(3);//停车场只允许停3辆车
System.out.println("车库未停任何车辆......");
for (int i=1;i<=5;i++){
Thread thread=new Thread(new Car("粤A"+i,semaphore));
thread.start();
}
}
static class Car implements Runnable{
private String name;
private Semaphore semaphore;
public Car(String name, Semaphore semaphore) {
this.name = name;
this.semaphore = semaphore;
}
@Override
public void run() {
try {
semaphore.acquire();//进入车库,获取入库证
System.out.println("+ "+name+"开进车库");
parking();
semaphore.release();//退出车库,退还入库证
System.out.println("- "+name+"已经离开车库");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void parking() {
System.out.println(name+"停车中");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果如下,程序中限制了车位为3,但是停车数量为5,意味着总有两部车要等待前面的车辆空出车位才能入库。
车库未停任何车辆......
+ 粤A1开进车库
粤A1停车中
+ 粤A2开进车库
粤A2停车中
+ 粤A3开进车库
粤A3停车中
- 粤A1已经离开车库
+ 粤A4开进车库
+ 粤A5开进车库
- 粤A2已经离开车库
粤A5停车中
粤A4停车中
- 粤A3已经离开车库
- 粤A5已经离开车库
- 粤A4已经离开车库