多线程之Semaphore

多线程之Semaphore

1 说明

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

public static void main(String[] args) {
     // 1. 创建 semaphore 对象
     Semaphore semaphore = new Semaphore(3);
    
     // 2. 10个线程同时运行
     for (int i = 0; i < 10; i++) {
         new Thread(() -> {
             // 3. 获取许可
             try {
                 semaphore.acquire();
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             try {
                 log.debug("running...");
                 sleep(1);
                 log.debug("end...");
             } finally {
                 // 4. 释放许可
                 semaphore.release();
             }
         }).start();
     }
 }

运行结果:

07:35:15.485 c.TestSemaphore [Thread-2] - running... 
07:35:15.485 c.TestSemaphore [Thread-1] - running... 
07:35:15.485 c.TestSemaphore [Thread-0] - running... 
07:35:16.490 c.TestSemaphore [Thread-2] - end... 
07:35:16.490 c.TestSemaphore [Thread-0] - end... 
07:35:16.490 c.TestSemaphore [Thread-1] - end... 
07:35:16.490 c.TestSemaphore [Thread-3] - running... 
07:35:16.490 c.TestSemaphore [Thread-5] - running... 
07:35:16.490 c.TestSemaphore [Thread-4] - running... 
07:35:17.490 c.TestSemaphore [Thread-5] - end... 
07:35:17.490 c.TestSemaphore [Thread-4] - end... 
07:35:17.490 c.TestSemaphore [Thread-3] - end... 
07:35:17.490 c.TestSemaphore [Thread-6] - running... 
07:35:17.490 c.TestSemaphore [Thread-7] - running... 
07:35:17.490 c.TestSemaphore [Thread-9] - running... 
07:35:18.491 c.TestSemaphore [Thread-6] - end... 
07:35:18.491 c.TestSemaphore [Thread-7] - end... 
07:35:18.491 c.TestSemaphore [Thread-9] - end... 
07:35:18.491 c.TestSemaphore [Thread-8] - running... 
07:35:19.492 c.TestSemaphore [Thread-8] - end... 

2 应用

  • Semaphore 限流,在访问高峰期时,让请求线程阻塞,高峰期过去再释放许可,当然它只适合限制单机 线程数量,并且仅是限制线程数,而不是限制资源数.

  • Semaphore 实现简单连接池,对比『享元模式』下的实现(用wait notify),性能和可读性显然更好.

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;
             }
         }
     }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值