Java---Semaphore

25 篇文章 0 订阅
11 篇文章 0 订阅

一.概念

Semaphore(信号量)可以用来控制同时访问特定资源的线程数量,常用于限流场景。Semaphore支持公平锁和非公平锁。

Semaphore接收一个int整型值,表示 许可证数量, 如果许可证剩余数量大于零时,线程则允许访问该共享资源;如果许可证剩余数量为零时,则拒绝线程访问该共享资源。 Semaphore所维护的许可证数量就是允许访问共享资源的最大线程数量。 所以,线程想要访问共享资源必须从Semaphore中获取到许可证。

二.原理

Semaphore内部主要通过AQS(AbstractQueuedSynchronizer)实现线程的管理。Semaphore在构造时,需要传入许可证的数量,它最后传递给了AQS的state值。线程在调用acquire方法获取许可证时,如果Semaphore中许可证的数量大于0,许可证的数量就减1,线程继续运行,当线程运行结束调用release方法时释放许可证时,许可证的数量就加1。如果获取许可证时,Semaphore中许可证的数量为0,则获取失败,线程进入AQS的等待队列中,等待被其它释放许可证的线程唤醒。

三.示例

假定商场的卫生间一共有三个位置,所以超过三个人时,后面的需要排队,当有位置空出是,后面进行补位。。。

package com.example.demo;


import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.Semaphore;

public class Person implements Runnable {
    private Semaphore wc;
    private String name;

    public Person(Semaphore wc, String name) {
        this.wc = wc;
        this.name = name;
    }

    @Override
    public void run() {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
            Random random = new Random();

            wc.acquire();
            System.out.println(
                    sdf.format(new Date()) + " " + name + " 进卫生间...");
            Thread.sleep((long) (random.nextDouble() * 5000) + 2000);
            System.out.println(
                    sdf.format(new Date()) + " " + name + " 出卫生间!");
            wc.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.example.demo;


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;

public class SemaphoreTester {
    public static void main(String[] args) throws InterruptedException {
        //卫生间只有三个位置,所以初始化许可证的总数为3。
        Semaphore washbasin = new Semaphore(3);

        List<Thread> threads = new ArrayList<>(6);
        threads.add(new Thread(new Person(washbasin, "小明")));
        threads.add(new Thread(new Person(washbasin, "小阳")));
        threads.add(new Thread(new Person(washbasin, "小张")));
        threads.add(new Thread(new Person(washbasin, "小赵")));
        threads.add(new Thread(new Person(washbasin, "小强")));
        threads.add(new Thread(new Person(washbasin, "小超")));
        for (Thread thread : threads) {
            thread.start();
            Thread.sleep(50);
        }
    }
}

结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值