网站建设考评表,怎么做网站域名指向,想接做网站的单子,国内十大高端定制西服品牌作者 | 王磊来源 | Java中文社群#xff08;ID#xff1a;javacn666#xff09;转载请联系授权#xff08;微信ID#xff1a;GG_Stone#xff09;大家好#xff0c;我是 Semaphore#xff0c;我的中文名字叫“信号量”#xff0c;我来自 JUC 家族#xff08;java.uti… 作者 | 王磊来源 | Java中文社群IDjavacn666转载请联系授权微信IDGG_Stone大家好我是 Semaphore我的中文名字叫“信号量”我来自 JUC 家族java.util.concurrent。我们家族有很多优秀的成员比如CountDownLatch等待其他线程都执行完再执行某线程CyclicBarrier循环阻塞一组线程直到某个事件达成当然我也不比他们弱哦 罒ω罒。以下是我的个人简历希望各位读者老爷们给个好评和三连先在此谢过了~基本信息姓名Semaphore中文名计数信号量出生日期JDK 1.5籍贯JUCjava.util.concurrent用途Java 中的一个同步器与 CountDownLatch 和 CyclicBarrier 不同Semaphore 是用来管理许可证的线程在调用 acquire() 方法时如果没有许可证那么线程就会阻塞等待直到有许可证时才能继续执行。许可证使用 release() 方法来发布发布一个许可证调用 acquire() 方法时如果有证书会减少许可证并继续执行后面的代码如果没有证书只能阻塞等待许可证而 Semaphore 在创建时会声明许可证的最大数量。专业技能我的专业技能就是“管理证书”使用此技能可以轻松的实现「限流」功能。什么是限流比如五一小长假快到了到那时会有大量的人去各个景区游玩但是每个景区能容纳的人是有限的比如大西安的大唐芙蓉园它的日承载量是 6 万人次也就是说每天最多能让 6 万来这里游玩但五一的时候会来很多的人比如突然来了 10 万人那这个时候就只能「限流」排队等待入园了。也就说大唐芙蓉园会让 6 万人先进去玩剩余的人在门口等待排队当有人从里面出来的时候才允许另一个排队的人进去。工作人员会把人数始终控制在 6 万人以下这样做的目的是为了让游玩的人有一个好的体验不至于造成一些意外事故比如踩踏事件什么的一定程度上保证了社会的稳定也便于景区良好的口碑建立和日后的正常运营而这种排队限制最大人数的行为就是「限流」。再来举个例子比如以车辆的限号来说它也是限流的一种常见场景。这样做的好处一方面是可以保护环境尽可能少一些碳排放另一方面能有效的缓解上、下班高峰时段的拥堵情况。尤其是在大西安很难想象如果不限号那么会堵成什么样PS让原本本不富裕的生活更是雪上加霜...咱们再从生活中的事例回到程序当中假设一个程序只能为 10W 人提供服务突然有一天因为某个热点事件造成了系统短时间内的访问量迅速增加到了 50W那么导致的直接结果是系统崩溃任何人都不能用系统了显然只有少人数能用远比所有人都不能用更符合我们的预期因此这个时候我们要使用「限流」了。使用Semaphore实现限流Semaphore 在创建的时候可以设置证书的数量相当于设置了限流的最大值再通过 release() 方法来发放证书通过 acquire() 方法来阻塞并等待证书这样就通过控制证书的方式来实现限流功能了。项目经验接下来咱们使用代码的方式来演示 Semaphore 的使用。我们以停车场的限流为例假设整个停车场只有 2 个车位车位虽少但足矣说明问题但来停车的却有 5 辆车显然车位不够用了此时需要保证停车场最多只能有 2 辆车接下来咱们使用 Semaphore 来实现车辆的限流功能具体实现代码如下import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;/*** Author磊哥* ByJava中文社群*/
public class SemaphoreExample {// 创建信号量static Semaphore semaphore new Semaphore(2);public static void main(String[] args) {// 创建 5 个固定的线程数ExecutorService threadPool Executors.newFixedThreadPool(5);// 定义执行任务Runnable runnable new Runnable() {Overridepublic void run() {// 拿到当前线程的名称String tname Thread.currentThread().getName();System.out.println(String.format(老司机%s停车场外排队时间%s,tname, new Date()));try {// 执行此行让所有线程先排队等待进入停车场Thread.sleep(100);// 执行阻塞semaphore.acquire();System.out.println(String.format(老司机%s已进入停车场时间%s,tname, new Date()));Thread.sleep(1000);System.out.println(String.format(老司机%s离开停车场时间%s,tname, new Date()));// 释放锁semaphore.release();} catch (InterruptedException e) {e.printStackTrace();}}};// 执行任务 1threadPool.submit(runnable);// 执行任务 2threadPool.submit(runnable);// 执行任务 3threadPool.submit(runnable);// 执行任务 4threadPool.submit(runnable);// 执行任务 5threadPool.submit(runnable);// 等线程池任务执行完之后关闭threadPool.shutdown();}
}
以上代码的执行结果如下从上述的结果我们可以看出当有 5 辆车同时需要进入停车场时因为停车场的停车位只有 2 个所以停车场最多只能容纳 2 辆车。此时我们通过 Semaphore 的 acquire 方法阻塞等待和 release 方法颁发一个证书顺利的实现了限流的功能让停车场的车辆数始终控制在 2 辆车以下等于或小于 2 辆车。个人评价我Semaphore实现证书控制手段有两种一种公平模式和非公平模式当然为了执行的性能考虑默认情况下我采取的是非公平的方式具体实现可见源码public Semaphore(int permits) {sync new NonfairSync(permits); // 非公平模式
}
关于公平模式和非公平模式所谓的公平模式就是以调用 acquire() 的先后顺序来决定获取许可证的顺序的公平模式遵循先进先出FIFO原则而非公平模式是抢占式的也就是有可能一个新的获取线程恰好在一个许可证释放时得到了这个许可证而前面还有等待的线程。显然使用非公平的模式性能更高因为它会把许可证发放给刚好准备好的线程而不用再根据先后顺序去“叫号”了。使用公平模式当然你可以手动选择使用公平模式来运行 SemaphoreSemaphore 提供了两个构造函数源码如下public Semaphore(int permits) {sync new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) {sync fair ? new FairSync(permits) : new NonfairSync(permits);
}
如果想用公平模式就可以使用第二个构造函数 Semaphore(int permits, boolean fair)将 fair 值设置为 true 就是公平模式来获取证书了。其他补充我还提供了一些其他方法用于实现更多的功能详情如下int availablePermits()返回此信号量中当前可用的许可证数。int getQueueLength()返回正在等待获取许可证的线程数。boolean hasQueuedThreads()是否有线程正在等待获取许可证。boolean isFair()查询 Semaphore 使用的是公平模式还是非公平模式如果此信号量使用的是公平模式则返回 true。void release(int permits)释放给定数量的许可证将其返回到信号量。tryAcquire()从这个信号量获得许可证只有在调用时可以使用该许可证。tryAcquire(int permits)从这个信号量获取给定数量的许可证只有在调用时全部可用。tryAcquire(int permits, long timeout, TimeUnit unit)从该信号量获取给定数量的许可证如果在给定的等待时间内全部可用并且当前线程尚未 interrupted。tryAcquire(long timeout, TimeUnit unit)如果在给定的等待时间内可用并且当前线程尚未 到达 interrupted则从该信号量获取许可。void reducePermits(int reduction) 减少可用的许可证数量 reduction 个它是 protected 方法。Collection getQueuedThreads() 返回所有等待获取许可证的线程集合它是 protected 方法。总结Semaphore 信号量是用来管理一组证书的默认情况下它采取的是非公平的方式来管理证书这样做的目的是为了实现高性能。Semaphore 中包含了两个重要的方法release() 方法发布一个许可证书acquire() 方法阻塞并等待一个证书。当线程调用了 acquire() 方法只有拥有了证书才能继续执行因此可以使用 Semaphore 来实现限流。
往期推荐
CyclicBarrier人齐了老司机就发车了CountDownLatch别浪等人齐再团