知道公司抢“坑位”是什么意思吗?

您所在的位置:网站首页 坑位是啥意思网络用语怎么说 知道公司抢“坑位”是什么意思吗?

知道公司抢“坑位”是什么意思吗?

2024-07-11 19:24| 来源: 网络整理| 查看: 265

一、 故事起源

很久很久以前,大概也就是昨天,肠胃作祟,急需排泄,提裤奔跑,进入厕所,

左右扫视,没有坑位,灵光一闪,换了楼层,找到坑位, 拉完粑粑接着回去写bug。

二、不安现状

身为程序员的我,想着改变世界,但遗憾暂未实现。改变一个厕所总可以吧,我不配吗?

所以我打算写一个程序来模拟厕所剩余坑位(当然了,业务上可能不会这样写,我之所以写这种代码是为了学习Semaphore,你应该懂我的良苦用心,还有就是不要给我找多线程的问题,这个示例禁不起大佬review,因为我过得浑浑噩噩。)

1. 代码先上

wc.java

import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; /** * @author 发现更多精彩 关注公众号:木子的昼夜编程 * 一个生活在互联网底层,做着增删改查的码农,不谙世事的造作 */ public class WC { // 假设一共有2个坑位(真少哈哈) private Semaphore s = new Semaphore(2); // 查看剩余坑位 public int surplus(){ // 获取剩余可用凭证数 return s.availablePermits(); } // 找坑位 public void enter(String name){ // 尝试找坑 boolean b = s.tryAcquire(); if (b) { System.out.println(name+"来了,有坑位,开始占用"); // 模拟占用时间 sleepRandom(); // 释放凭证 s.release(); System.out.println("爽呆呆,"+name+"释放坑位"); } else { System.out.println(name+"来了,木有空位,伤心离去"); } } // 随机让线程睡会儿 模拟占坑时间 private void sleepRandom(){ try { int random=(int)(Math.random()*10+1); Thread.sleep(TimeUnit.SECONDS.toMillis(random)); } catch (InterruptedException e) { e.printStackTrace(); } } }

Test.java

/** * @author 发现更多精彩 关注公众号:木子的昼夜编程 * 一个生活在互联网底层,做着增删改查的码农,不谙世事的造作 * @create 2021-09-19 9:25 */ public class Test { public static void main(String[] args) { WC wc = new WC(); // 多个人进入厕所 new Thread(()-> wc.enter("小强")).start(); new Thread(()-> wc.enter("小月月")).start(); new Thread(()-> wc.enter("小月鸟")).start(); // 小明比较聪明 先从程序看看有没有坑位 有再去没有就不去了 new Thread(()->{ int sp = wc.surplus(); // 如果有坑再去(但是不一定去了就有,说不定刚好别人占了呢) if (sp > 0) { wc.enter("小明"); } else { System.out.println("小明知道没坑,先不去"); } }).start(); } }

输出结果:

在这里插入图片描述

2. 理论跟上

咦? 好神奇,一个Semaphore就能实现。对,就是这么牛.

这时候就有人问了,他是怎么实现这么高级的功能的,少年你是问出这个问题的时候我就知道你没有看我前边的文章(这时候可以关注:木子的昼夜编程 发现更多精彩)。

他之所以这么厉害,是因为他有一个好友名字叫做:AbstractQueuedSynchronizer 用我蹩脚的英语翻译:抽象队列同步器,不重要,每个人都有小名,你可以叫他小名:AQS 。

AOS人品极好,他有很多朋友,有你熟悉的ReentrantLock、CountDownLatch 等

这里再简单介绍一下我们的兄弟AQS吧。 他的主要构成有两个:state , queue

state: 记录可用凭证数(剩余坑位)

queue: 记录等待获取凭证的线程(厕所外排队拉粑粑的人)

获取坑的流程是这样的:

在这里插入图片描述

看着是不是很简单,判断是否有空位,有就进入,没有就排队,等待有空位再进入。

越简单的事情其实越复杂,比如为什么 1+1 = 2 。

3. 聊聊我们的 Semaphore方法 import java.util.concurrent.Semaphore; /** * @author 发现更多精彩 关注公众号:木子的昼夜编程 * 一个生活在互联网底层,做着增删改查的码农,不谙世事的造作 * @create 2021-09-19 10:51 */ public class TestMethod { public static void main(String[] args) throws InterruptedException { Semaphore s = new Semaphore(2); //(常用) 尝试获取凭证,直到获取到凭证或者线程被中断 s.acquire(); // acquire()加强版,可以一次获取多个凭证,屁股大占俩坑位 s.acquire(2); // 尝试获取凭证,直到获取到凭证 s.acquireUninterruptibly(); // acquireUninterruptibly()的加强版 可以一次获取多个凭证 s.acquireUninterruptibly(2); // 不会死等 尝试获取 获取不到就返回false 获取到就返回true // 用一个成语来形容叫:浅尝辄止 boolean b = s.tryAcquire(); // tryAcquire() 加强版 boolean nb = s.tryAcquire(10); // 查询剩余凭证 其实就是state的值 s.availablePermits(); //(常用) 释放凭证 也就是离开坑位 这里需要注意,多次release 凭证会变多 // 也就是release 100次 坑位就会多出100个 这个业务上需要注意,必须acquire才能release // 不然大家一看100个坑位 都去了那不打起来了吗 s.release(); // s.release();加强版 释放多个凭证 s.release(2); // 这个方法绝了 获取所有剩余凭证并返回凭证数量 // 有点儿像保洁阿姨,大喊一声:别进来了,我要开始打扫了。 // drain:排水;排空;(使)流光;放干;(使)流走,流出;喝光;喝干 int count = s.drainPermits(); // 获取AQS的实现是否是公平模式 这个就涉及到公平、非公平了 后边再聊 boolean fair = s.isFair(); // 看有多少人排队 int queueLength = s.getQueueLength(); // 看是否还有排队的人 有就返回true 没有返回false boolean b1 = s.hasQueuedThreads(); } } 4. AQS 对朋友的标准是什么

AQS说了,我有我的原则,你们只要遵循我的原则,我们就能成为好朋友。

原则是什么呢?AQS定义了很多方法,但是都是空实现,他的朋友们需要实现这些方法。

这不就是“模板方法”模式。

包括但不限于以下方法:

protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); } protected boolean tryRelease(int arg) { throw new UnsupportedOperationException(); } protected int tryAcquireShared(int arg) { throw new UnsupportedOperationException(); } protected boolean tryReleaseShared(int arg) { throw new UnsupportedOperationException(); }

我们拿tryAcquire 举例调用链是这样的:

在这里插入图片描述

AQS定义了流程,朋友在遵循流程的基础上进行自我发挥就好了。

我们来看一下代码简单流程:

在这里插入图片描述

5.Semaphore的属性sync

sync是Semaphore属性,他可能是FairSync 也可能是NonfairSync

// AQS子类 abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 1192457210091910933L; // 设置凭证 调用AQS方法 Sync(int permits) { setState(permits); } // 获取凭证 调用AQS方法 final int getPermits() { return getState(); } // 默认实现了一个非公平的获取凭证方式 // 这里大家可能有疑问,就是公平和非公平有什么不一样下边我画个图解释一下 // 抢坑位 final int nonfairTryAcquireShared(int acquires) { for (;;) { // 获取可用凭证数 int available = getState(); // 可用凭证数-申请凭证数 int remaining = available - acquires; // 如果remaining小于0 也就是凭证不够 // 或者cas设置state成功(获取凭证成功) // 返回剩余凭证数 if (remaining 0 || h == null || h.waitStatus


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3