8.2 JUC - 4.Semaphore

目录

一、是什么?

Semaphore:信号量,用来限制能同时访问共享资源的线程上限

二、简单使用

java 复制代码
public class TestSemaphore {
    public static void main(String[] args) {
        // 1. 创建 semaphore 对象
        Semaphore semaphore = new Semaphore(3);

        // 2. 10个线程同时运行
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    log.debug("running...");
                    sleep(1);
                    log.debug("end...");
                } finally {
                    semaphore.release();
                }
            }).start();
        }
    }
}

结果:始终只有三个线程处于正在运行的状态

三、semaphore应用

  • 使用semaphore限流,在访问高峰期时,让请求线程阻塞。当然它只适合限制单机 线程数量,并且是仅限制线程数,而不是限制资源数(例如连接数)
  • 使用Semaphore实现简单连接池,对比享元模式下的实现(用wait和notify),性能和可读性要更好
java 复制代码
class Pool {
    // 1. 连接池大小
    private final int poolSize;

    // 2. 连接对象数组
    private Connection[] connections;

    // 3. 连接状态数组 0 表示空闲, 1 表示繁忙
    private AtomicIntegerArray states;

    private Semaphore semaphore;

    // 4. 构造方法初始化
    public Pool(int poolSize) {
        this.poolSize = poolSize;
        // 让许可数与资源数一致
        this.semaphore = new Semaphore(poolSize);
        this.connections = new Connection[poolSize];
        this.states = new AtomicIntegerArray(new int[poolSize]);
        for (int i = 0; i < poolSize; i++) {
            connections[i] = new MockConnection("连接" + (i+1));
        }
    }

    // 5. 借连接
    public Connection borrow() {// t1, t2, t3
        // 获取许可
        try {
            semaphore.acquire(); // 没有许可的线程,在此等待
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < poolSize; i++) {
            // 获取空闲连接
            if(states.get(i) == 0) {
                if (states.compareAndSet(i, 0, 1)) {
                    log.debug("borrow {}", connections[i]);
                    return connections[i];
                }
            }
        }
        // 不会执行到这里
        return null;
    }
    // 6. 归还连接
    public void free(Connection conn) {
        for (int i = 0; i < poolSize; i++) {
            if (connections[i] == conn) {
                states.set(i, 0);
                log.debug("free {}", conn);
                semaphore.release();
                break;
            }
        }
    }
}

四、Semaphore原理


相关推荐
王嘉俊9254 分钟前
设计模式--适配器模式:优雅解决接口不兼容问题
java·设计模式·适配器模式
王嘉俊9255 分钟前
设计模式--组合模式:统一处理树形结构的优雅设计
java·设计模式·组合模式
道199313 分钟前
50 台小型无人车与50套穿戴终端 5 公里范围内通信组网方案深度研究
java·后端·struts
迎風吹頭髮18 分钟前
UNIX下C语言编程与实践35-UNIX 守护进程编写:后台执行、脱离终端、清除掩码与信号处理
java·c语言·unix
光军oi34 分钟前
全栈开发杂谈————JAVA微服务全套技术栈详解
java·开发语言·微服务
帮帮志35 分钟前
目录【系列文章目录】-(关于帮帮志,关于作者)
java·开发语言·python·链表·交互
聪明的笨猪猪35 分钟前
Java Spring “MVC ”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
Boop_wu2 小时前
[数据结构] Map和Set
java·数据结构·算法
一勺菠萝丶2 小时前
Mac 上用 Homebrew 安装 JDK 8(适配 zsh 终端)完整教程
java·python·macos
毕设源码-朱学姐4 小时前
【开题答辩全过程】以 办公自动化管理系统为例,包含答辩的问题和答案
java·eclipse