• Java高并发编程基础三大利器


    1. 什么是Semaphore

    Semaphore(信号量)是用来控制同时访问特定资源的线程数量, 它通过协调各个线程, 以保证合理的使用公共资源。

    比喻解释:

    我们可以把Semaphore比作是控制流量的红绿灯。
    eg:
    XX马路要限制流量, 只允许同时有一百辆车在这条路上行使, 其他的都必须在路口等待。
    如果前一百辆车看到绿灯, 可以开进这条马路;
    后面的车会看到红灯, 不能驶入XX马路。
    但是如果前一百辆中有五辆车已经离开了XX马路, 那么后面就允许有5辆车驶入马路。

    这个例子里说的车就是线程
    驶入马路就表示线程在执行
    离开马路就表示线程执行完成
    看见红灯就表示线程被阻塞, 不能执行

    2. 实际例子


    Semaphore机制是提供给线程抢占式获取许可,所以他可以实现公平或者非公平,类似于ReentrantLock。


    说了这么多我们来个实际的例子看一看。

    eg:
    我们去停车场停车,停车场总共只有5个车位,
    但是现在有8辆汽车来停车,剩下的3辆汽车要么等其他汽车开走后进行停车。

    代码:

    public class SemaphoreTest {
        public static void main(String[] args) throws InterruptedException {
             // 初始化五个车位
            Semaphore semaphore = new Semaphore(5);
            // 等所有车子
            final CountDownLatch latch = new CountDownLatch(8);
            for (int i = 0; i < 8; i++) {
                int finalI = i;
                if (i == 5) {
                    Thread.sleep(1000);
                    new Thread(() -> {
                        stopCarNotWait(semaphore, finalI);
                        latch.countDown();
                    }).start();
                    continue;
                }
                new Thread(() -> {
                    stopCarWait(semaphore, finalI);
                    latch.countDown();
                }).start();
            }
            latch.await();
            log("总共还剩:" + semaphore.availablePermits() + "个车位");
        }
    
        private static void stopCarWait(Semaphore semaphore, int finalI) {
            String format = String.format("车牌号%d", finalI);
            try {
                semaphore.acquire(1);
                log(format + "找到车位了,去停车了");
                Thread.sleep(10000);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                semaphore.release(1);
                log(format + "开走了");
            }
        }
    
        private static void stopCarNotWait(Semaphore semaphore, int finalI) {
             String format = String.format("车牌号%d", finalI);
            try {
                if (semaphore.tryAcquire()) {
                    log(format + "找到车位了,去停车了");
                    Thread.sleep(10000);
                    log(format + "开走了");
                    semaphore.release();
                } else {
                    log(format + "没有停车位了,不在这里等了去其他地方停车去了");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        public static void log(String content) {
            // 格式化
            DateTimeFormatter fmTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            // 当前时间
            LocalDateTime now = LocalDateTime.now();
            System.out.println(now.format(fmTime) + "  "+content);
        }
    }

    运行结果:

    2021-04-20 18:54:57 车牌号0找到车位了,去停车了
    2021-04-20 18:54:57 车牌号3找到车位了,去停车了
    2021-04-20 18:54:57 车牌号2找到车位了,去停车了
    2021-04-20 18:54:57 车牌号1找到车位了,去停车了
    2021-04-20 18:54:57 车牌号4找到车位了,去停车了
    2021-04-20 18:54:58 车牌号5没有停车位了,不在这里等了去其他地方停车去了
    2021-04-20 18:55:07 车牌号7找到车位了,去停车了
    2021-04-20 18:55:07 车牌号6找到车位了,去停车了
    2021-04-20 18:55:07 车牌号2开走了
    2021-04-20 18:55:07 车牌号0开走了
    2021-04-20 18:55:07 车牌号3开走了
    2021-04-20 18:55:07 车牌号4开走了
    2021-04-20 18:55:07 车牌号1开走了
    2021-04-20 18:55:17 车牌号7开走了
    2021-04-20 18:55:17 车牌号6开走了
    2021-04-20 18:55:17 总共还剩:5个车位

    技术改变世界
  • 相关阅读:
    spring mvc之DispatcherServlet类分析
    python根据操作系统类型调用特定模块
    C#编写windows服务程序
    写在开始前---多端小系统结构
    写在开始前---web异常处理
    java反射
    写在开始前---简单业务分层
    写在开始前---ajax中的会话过期与重新登录
    一个简易的netty udp服务端
    google的python语言规范
  • 原文地址:https://www.cnblogs.com/davidgu/p/14683115.html
Copyright © 2020-2023  润新知