一.场景引入
现在有6个车,要抢占三个车位,占用车位几秒后,离开车位
二.代码示例
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 6 ; i++) {
new Thread(()->{
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"\t抢占到了车位");
//暂停一会线程
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+"\t离开了车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
},String.valueOf(i)).start();
}
}
运行结果:
"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" "-javaagent:D:\idea\IntelliJ IDEA 2019.2.3\lib\idea_rt.jar=56223:D:\idea\IntelliJ IDEA 2019.2.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;C:\Users\李肇京\IdeaProjects\JUC\out\production\JUC" JUC_01_SellTicket.HelperClasses.SemaphoreDemo
1 抢占到了车位
2 抢占到了车位
3 抢占到了车位
1 离开了车位
4 抢占到了车位
2 离开了车位
5 抢占到了车位
3 离开了车位
6 抢占到了车位
4 离开了车位
5 离开了车位
6 离开了车位
Process finished with exit code 0
三.Semaphore介绍
- JDK官方:一个计数信号量。 在概念上,信号量维持一组许可
- 在信号量上我们定义两种操作:
- acquire(获取) 当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),要么一直等下去,直到有线程释放信号量,或超时
- release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。
这里我们通过信号量的构造方法传入一个限制参数为3,说明最多有三个线程占用资源,acquire有两种结果,一种是拿到信号量,信号量减一;要么没拿到,则阻塞。此处我们有三个车没有拿到,为阻塞状态,但是当占用车位的线程调用release后,之前没进过车位的也有机会进入了。而且已经进过车位的线程因为已经运行结束了,所以无法再次抢占资源
- 信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制。