并发控制-信号量(Semaphore)
信号量用来控制有限资源的方法,举例:假如信号量为3,则同时只有3个线程共享。
概述
信号量用来控制系统耗时资源的访问,一般我们初始设置了一个公平的信号量,线程在使用时需要申请,用完之后需要释放。
使用流程
信号量Semaphore的使用流程如下:
一般设置公平的信号量-->线程在使用时需要进行require申请-->若可以申请到,则执行自己的逻辑-->执行完成后,需要释放信号量
-->若未申请到,则可以阻塞,直到申请到。
主要方法
信号量的部分常用方法如下:
1.信号量构造:public Semaphore(int permits, boolean fair)
2.获取信号量:public void acquire();acquireUninterruptibly();tryAcquire() ;tryAcquire(long timeout, TimeUnit unit)
3.释放信号量:release();release(int permits)
实例代码
下面我们通过初始化一个3容量的信号量,我们用100个线程去获取这个信号量,每次申请一个信号量,当用完之后,我们释放这一个,如以下实例代码所示:
package com.yang.concurrent; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.stream.IntStream; public class SemaphoreDemp { static Semaphore semaphore =new Semaphore(3,true); public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 100; i++) { Runnable runnable = new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName()+"等待获取信号量"); semaphore.acquire(); System.out.println(Thread.currentThread().getName()+"取到了信号量"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }finally { System.out.println(Thread.currentThread().getName()+"释放信号量"); semaphore.release(); } } }; executorService.submit(runnable); } executorService.shutdown(); } }
运行结果如下图所示:
特殊用法及注意点
1.申请和释放的信号量必须保持一致,在信号量申请时,比如我们可以申请2个,释放的时候也可以释放2个,这个场景是指程序在运行时,可能需要多个资源
2.信号量在初始化的时候,可以设置为公平或者非公平,我们一般设置为公平,对耗时长的资源访问时,一般不允许争夺
3.信号量在获取和释放时,对是否是同一个线程没有限制。