JAVA并发包-同步工具(3)---Semaphore信号量
发布日期:2021-06-30 13:44:54 浏览次数:2 分类:技术文章

本文共 2298 字,大约阅读时间需要 7 分钟。

Semaphore可以控制系统流量,拿到信号量的可以进入,否则就等待,通过acquire和release方法获取和释放访问许可。

举例:

package com.day20180312;import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;/** * 我们以一个停车场运作为例来说明信号量的作用。假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了三辆车,看门人允许其中它们进入进入,然后放下车拦。 * 以后来的车必须在入口等待,直到停车场中有车辆离开。这时,如果有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开一辆,则又可以放入一辆,如此往复。       在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。        信号量是一个非负整数,表示了当前公共资源的可用数目(在上面的例子中可以用空闲的停车位类比信号量),当一个线程要使用公共资源时(在上面的例子中可以用车辆类比线程),        首先要查看信号量,如果信号量的值大于1,则将其减1,然后去占有公共资源。        如果信号量的值为0,则线程会将自己阻塞,直到有其它线程释放公共资源。 * 在创建Semaphore对象的时候还可以指定它的公平性。 * 一般常用非公平的信号量,非公平信号量是指在获取许可时先尝试获取许可,而不必关心是否已有需要获取许可的线程位于等待队列中,如果获取失败,才会入列。 * 而公平的信号量在获取许可时首先要查看等待队列中是否已有线程,如果有则入列。 *  * 在信号量上我们定义两种操作: acquire(获取) 和 release(释放)。 * 当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),要么一直等下去,直到有线程释放信号量,或超时。 * release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。       信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制。 * 构造函数源代码//非公平的构造函数public Semaphore(int permits) {   sync = new NonfairSync(permits);}//通过fair参数决定公平性public Semaphore(int permits, boolean fair) {   sync = fair ? new FairSync(permits) : new NonfairSync(permits);} * @author jeff * 2018年6月2日 */public class TestSemaphore {//参数permits表示许可数:3private Semaphore smp = new Semaphore(3); //随机数private Random rnd = new Random();//任务线程class TaskDemo implements Runnable{private String id;TaskDemo(String id){this.id = id;}@Overridepublic void run(){  try {        smp.acquire();//获取信号量 --》获取成功,则许可数减1,如果许可数为0则获取失败,线程阻塞,进入AQS等待队列中,它会被其它释放许可的线程唤醒        System.out.println("Thread " + id + " is working");//成功获取信号量 打印工作线程Id        Thread.sleep(rnd.nextInt(1000));        smp.release();//释放信号量,许可数加1        System.out.println("Thread " + id + " is over");  } catch (InterruptedException e) {  } }}/*** 创建多个任务:* 可以看出,最多同时有三个线程并发执行,也可以认为有三个公共资源* @param args*/public static void main(String[] args){TestSemaphore semaphoreDemo = new TestSemaphore();//注意我创建的线程池类型,ExecutorService se = Executors.newCachedThreadPool();se.submit(semaphoreDemo.new TaskDemo("a"));se.submit(semaphoreDemo.new TaskDemo("b"));se.submit(semaphoreDemo.new TaskDemo("c"));se.submit(semaphoreDemo.new TaskDemo("d"));se.submit(semaphoreDemo.new TaskDemo("e"));se.submit(semaphoreDemo.new TaskDemo("f"));se.shutdown();}}

 

转载地址:https://jeffsheng.blog.csdn.net/article/details/80551397 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:每天一例多线程[day1]-----synchronized与锁竞争
下一篇:JAVA按顺序混合上传多文件和文本域

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年05月03日 03时46分51秒