Semaphore实战场景分析(附源码)

Semaphore概述

首先我们看一下官方给出该工具的定义👇👇👇
   A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly.
   Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource.
简单来说:
      1.Semaphore通过初始化维护了一组凭证,通过acquire()获取凭证否则会阻塞,执行完动作后,通过release()释放手中的凭证供下一个工作线程使用。
      2.Semaphore通常用于限制可以访问某些资源的线程数。
      3.Semaphore是一个计数器,并且计数可以重复使用,获取凭证释放凭证。

Semaphore实战之访问控制

   狗哥一直想自己创业,经过一段时间的努力,每月把女朋友们的工资都攒下,终于有了本金,由于女朋友按摩手法相当了得,狗哥本着造福大众,有福同享,有钱我赚的思想决定开一家正规按摩店💆💆💆。
   这就遇到个问题,只有三个女朋友的狗哥,同时只能接待三位客人,狗哥就在想啊,这怎么解决客人多了的按摩问题呢。想来想去只能进行限流,也不能让一个女朋友同时给多个客人按摩吧😰😰
   于是狗哥就设置了三个按摩凭证,客人拿到凭证后呢,就可以进房间享受按摩服务,出来之后再把凭证交还给狗哥保管。
   这时候有的客人就说了,我不想排队,我有钱能插队不。狗哥不是为了钱,只是为了满足客人的要求,又提出了周一到周五按排队顺序提供凭证,而周末则是价高者先得。
   这个需求怎么做呢,本质上是个流量控制,每次仅允许三位拿到凭证的客人进行按摩,按摩后交还凭证后下一位客人可以继续。还有个需要考虑的点就是获取凭证的公平及非公平的问题。是不是有点思路了?

package com.cn.scott.test;

import java.util.concurrent.Semaphore;

public class SemaphoreTest {


    static class Customer implements Runnable {

        private Semaphore semaphore;
        private Integer order;

        Customer(Integer order, Semaphore semaphore) {
            this.order = order;
            this.semaphore = semaphore;
        }

        @Override
        public void run() {
            String customerName = "客户" + order;
            System.out.println(customerName + "正在排队等待...");
            try {
                semaphore.acquire();
                System.out.println(customerName + "获取门票并且开始按摩");
                Thread.sleep(order * 1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                System.out.println(customerName + "按摩完毕,即将归还门票");
                semaphore.release();
            }
        }
    }


    public static void main(String[] args) {

        Semaphore semaphore = new Semaphore(3);
        for (int i = 1; i <= 5; i++) {
            new Thread(new Customer(i, semaphore)).start();
        }

    }
}


执行结果如下:
      客户1正在排队等待…
      客户4正在排队等待…
      客户1获取门票并且开始按摩
      客户2正在排队等待…
      客户2获取门票并且开始按摩
      客户3正在排队等待…
      客户5正在排队等待…
      客户4获取门票并且开始按摩
      客户1按摩完毕,即将归还门票
      客户3获取门票并且开始按摩
      客户2按摩完毕,即将归还门票
      客户5获取门票并且开始按摩
      客户4按摩完毕,即将归还门票
      客户3按摩完毕,即将归还门票
      客户5按摩完毕,即将归还门票

当我们想按顺序获取门票并进行按摩的时候,我们需要调用Semaphore的另外一个构造,代码如下👇👇:

		Semaphore semaphore1 = new Semaphore(3,true);
        for (int i = 1; i <= 5; i++) {
            new Thread(new Customer(i,semaphore1)).start();
        }

按排队顺序公平按摩的结果如下👇👇:
      客户1正在排队等待…
      客户3正在排队等待…
      客户2正在排队等待…
      客户2获取门票并且开始按摩
      客户3获取门票并且开始按摩
      客户4正在排队等待…
      客户1获取门票并且开始按摩
      客户5正在排队等待…
      客户1按摩完毕,即将归还门票
      客户4获取门票并且开始按摩
      客户2按摩完毕,即将归还门票
      客户5获取门票并且开始按摩
      客户3按摩完毕,即将归还门票
      客户4按摩完毕,即将归还门票
      客户5按摩完毕,即将归还门票

从执行结果不难看出我们已经实现了上述需求。接下来我们看看Semaphore提供的其他方法。

方法说明
acquire()从信号量获取一个许可,如果无可用许可前将一直阻塞等待
acquire(int permits)获取指定数目的许可,如果无可用许可前也将会一直阻塞等待
tryAcquire()从信号量尝试获取一个许可,如果无可用许可,直接返回false,不会阻塞
tryAcquire(int permits)尝试获取指定数目的许可,如果无可用许可直接返回false
tryAcquire(int permits, long timeout, TimeUnit unit)在指定的时间内尝试从信号量中获取许可,如果在指定的时间内获取成功,返回true,否则返回false
release()释放一个许可,别忘了在finally中使用,注意:多次调用该方法,会使信号量的许可数增加,达到动态扩展的效果
availablePermits()获取当前信号量可用的许可

小结

1.Semaphore是一个计数器,通过初始化的数值和其提供的方法来实现线程的控制。
2.Semaphore比较适合的场景是资源流量等控制。
3.Semaphore通过其提供的方法可以重复使用。
4.Semaphore提供的方法很多,通过灵活运用acquire(int permits)、release()等,可以在某些场景取代CountDownLatch或CyclicBarrier。
点赞收藏,富婆包养✋✋

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码大师麦克劳瑞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值