- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
Semaphore 通常我们叫它信号量, 可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。
可以把它简单的理解成我们停车场入口立着的那个显示屏,每有一辆车进入停车场显示屏就会显示剩余车位减1,每有一辆车从停车场出去,显示屏上显示的剩余车辆就会加1,当显示屏上的剩余车位为0时,停车场入口的栏杆就不会再打开,车辆就无法进入停车场了,直到有一辆车从停车场出去为止。
通常用于那些资源有明确访问数量限制的场景,常用于限流 。
比如:数据库连接池,同时进行连接的线程有数量限制,连接不能超过一定的数量,当连接达到了限制数量后,后面的线程只能排队等前面的线程释放了数据库连接才能获得数据库连接。
比如:停车场场景,车位数量有限,同时只能容纳多少台车,车位满了之后只有等里面的车离开停车场外面的车才可以进入。
在比如,接口限流 ,应用限流 ,商品限流…
acquire()
获取一个令牌,在获取到令牌、或者被其他线程调用中断之前线程一直处于阻塞状态。
tryAcquire(long timeout, TimeUnit unit)
尝试在指定时间内获得令牌,返回获取令牌成功或失败,不阻塞线程。
release()
释放一个令牌,唤醒一个获取令牌不成功的阻塞线程。
hasQueuedThreads()
等待队列里是否还存在等待线程。
getQueueLength()
获取等待队列里阻塞的线程数。
drainPermits()
清空令牌把可用令牌数置为0,返回清空令牌的数量。
availablePermits()
返回可用的令牌数量。
// .....其他的自己看源码
每个停车场入口都有一个提示牌,上面显示着停车场的剩余车位还有多少,当剩余车位为0时,不允许车辆进入停车场,直到停车场里面有车离开停车场,这时提示牌上会显示新的剩余车位数。
业务场景 :
1、停车场容纳总停车量10。
2、当一辆车进入停车场后,显示牌的剩余车位数响应的减1.
3、每有一辆车驶出停车场后,显示牌的剩余车位数响应的加1。
4、停车场剩余车位不足时,车辆只能在外面等待。
public class TestCar {
//停车场同时容纳的车辆10
private static Semaphore semaphore=new Semaphore(10);
public static void main(String[] args) {
//模拟100辆车进入停车场
for(int i=0;i<100;i++){
Thread thread=new Thread(new Runnable() {
public void run() {
try {
System.out.println("===="+Thread.currentThread().getName()+"来到停车场");
if(semaphore.availablePermits()==0){
System.out.println("车位不足,请耐心等待");
}
semaphore.acquire();//获取令牌尝试进入停车场
System.out.println(Thread.currentThread().getName()+"成功进入停车场");
Thread.sleep(new Random().nextInt(10000));//模拟车辆在停车场停留的时间
System.out.println(Thread.currentThread().getName()+"驶出停车场");
semaphore.release();//释放令牌,腾出停车场车位
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},i+"号车");
thread.start();
}
}
}
package com.limiting.semaphore;
import java.lang.annotation.*;
@Documented
@Target({ElementType.METHOD})//作用:方法
@Retention(RetentionPolicy.RUNTIME)
public @interface SemaphoreDoc {
String key(); //建议设置不然可能发生,不同方法重复限流现象
int limit() default 3;
int blockingTime() default 3;
}
package com.limiting.semaphore;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@Component
@Aspect
public class SemaphoreAop {
//这里需要注意了,这个是将自己自定义注解作为切点的根据,路径一定要写正确了
@Pointcut(value = "@annotation(com.limiting.semaphore.SemaphoreDoc)")
public void semaphoreDoc() {
}
//限流池
Map<String, Semaphore> map=new ConcurrentHashMap<>();
@Around("semaphoreDoc()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
Object res = null;
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
SemaphoreDoc annotation = signature.getMethod().getAnnotation(SemaphoreDoc.class);
int blockingTime = annotation.blockingTime();
int limit = annotation.limit();
String key = annotation.key();
StringBuilder name = new StringBuilder(key+signature.getMethod().getName());//方法名
for (String parameterName : signature.getParameterNames()) {
name.append(parameterName);
}
Semaphore semaphore = map.get(name.toString());
if (semaphore == null) {
Semaphore semaphore1 = new Semaphore(limit);
map.put(name.toString(),semaphore1);
semaphore=semaphore1;
}
try {
//获取令牌
boolean b = semaphore.tryAcquire(blockingTime, TimeUnit.SECONDS);
if (b) {//如果拿到令牌了那么执行方法
try {
res = joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
} else {
//在一定时间内拿不到令牌那么就访问失败
throw new Exception("访问超时,目前请求人数过多请稍后在试");
}
} finally {
//释放令牌,腾出位置
semaphore.release();
}
return res;
}
}
package com.limiting.semaphore;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* 秒杀防止商品超卖现象
*/
public class SemaphoreCommodity {
//商品池
private Map<String, Semaphore> map=new ConcurrentHashMap<>();
//初始化商品池
public SemaphoreCommodity() {
//手机10部
map.put("phone",new Semaphore(10));
//电脑4台
map.put("computer",new Semaphore(4));
}
/**
*
* @param name 商品名称
* @return 购买是否成功
*/
public boolean getbuy(String name) throws Exception {
Semaphore semaphore = map.get(name);
while (true) {
int availablePermit = semaphore.availablePermits();
if (availablePermit==0) {
//商品售空
return false;
}
boolean b = semaphore.tryAcquire(1, TimeUnit.SECONDS);
if (b) {
System.out.println("抢到商品了");
///处理逻辑
return true;
}
}
}
public static void main(String[] args) throws Exception {
SemaphoreCommodity semaphoreCommodity=new SemaphoreCommodity();
for (int i = 0; i < 10; i++) {
new Thread(()->{
try {
System.out.println(semaphoreCommodity.getbuy("computer"));
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
点赞 -收藏-关注-便于以后复习和收到最新内容有其他问题在评论区讨论-或者私信我-收到会在第一时间回复如有侵权,请私信联系我感谢,配合,希望我的努力对你有帮助^_^
请检查我对信号量的理解! 我理解计数信号量和二进制信号量背后的想法。然而,用 signal() 和 wait() 实现的自旋锁和信号量之间的区别对我来说有点混合在一起。 例如,自旋锁基本上有两个值(用
有人问我是否可以使用以下功能: void down(struct semaphore* sem); int down_intterruptible(struct semaphore* sem); 仅来
我创建了一个小型电影租赁模拟程序。它的工作原理如下:- 主线程让用户输入客户姓名 每个输入的客户都会启动一个新线程(Customer Runnable) 创建 5 个客户后,租赁服务开始(正在等待 5
我被要求编写测试用例来实际展示信号量和读写信号量在读者多而写者少的情况下的性能,反之亦然。我已经实现了信号量(在内核空间中我们实际上被问到)但不知道如何编写用例并对其进行现场实际评估(明确地)。 最佳
在 Java java.util.concurrent.Semaphore 文档中,我不太清楚如果 semaphore.acquire() 阻塞线程并随后被 InterruptedException
信号量是满足有限等待还是只是为了提供互斥? 最佳答案 答案 正如您将在下面看到的那样,理论上它可能会打破有界等待条件。实际上,它在很大程度上取决于使用哪种调度算法。 wait()的经典实现和 sign
我唯一理解的是 信号量是一种原始方式 关键区域有一个 GUARD 变量(信号量也有,但名称不是 GUARD!) ?? 那么有什么区别呢? 最佳答案 通常,临界区域是一个地方,如果存在两个单独的执行线程
我们有 3 个任务以不同的优先级运行:A (120)、B (110)、C (100)。A 采用带有反转安全标志的互斥信号量。任务 B 执行 semTake,这导致任务 A 的优先级提升到 110。随后
尝试构建我的 React 应用程序,但遇到此编译错误: /Users/jimvercoelen/Documents/bitbucket/inboundmuse-client/node_modules/
似乎 glib 提供互斥体和条件作为线程同步原语,但通用 semaphores 怎么样? (从某种意义上说,它们支持原始的 P 和 V 操作?)我对 GCond 的理解是否正确?相当于一个二进制信号量
我们有 3 个任务以不同的优先级运行:A (120)、B (110)、C (100)。A 采用带有反转安全标志的互斥信号量。任务 B 执行 semTake,这导致任务 A 的优先级提升到 110。随后
一般情况下如何用信号量来描述八个进程的同步上面的优先图? 最佳答案 p1 p2 p3 p4 p5 p6 p7
我正在阅读“操作系统概念”中有关信号量的内容(对于那些了解它的人),并且我认为我完全理解了信号量,直到我阅读了这段话: The critical aspect of semaphores is tha
JUC同步锁原理源码解析四----Semaphore Semaphore 1.Semaphore的来源
Semaphore 是什么 Semaphore 通常我们叫它信号量, 可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。 可以把它简单的理解成我们停车场入口立着的那个显示
如何在第一次测试失败时中断所有 Cypress 测试? 我们正在使用 semaphore 为每个 PR 使用 Cypress 启动完整的 e2e 测试。但这需要太多时间。 我想在第一次测试失败时中断所
有人知道为什么将信号量操作称为P和V吗?每次阅读有关信号量的章节时,都会显示如下内容: 为了使线程获得资源,它执行P操作。为了使线程释放资源,它执行V操作。 P和V代表什么?为什么它们不被称为等待和信
我正在尝试在python中使用信号量,但无法使其按我想要的方式工作。 我有以下代码: import os import threading import time sem = threading.Se
有什么办法可以找到吗 有多少线程在等待信号量? 当前有多少线程占用了信号量? 如果我使用线程池线程等待信号量,如何让主线程等待线程池线程完成。 谢谢。 最佳答案 这是线程同步中的禁忌知识。因为完全不可
我们可以通过 availablePermits() 获得剩余许可 如何在运行时获取 usedPermits() 或 maxPermits(例如,最大许可从 db 加载并且 db 值可能在信号量创建后发
我是一名优秀的程序员,十分优秀!