当前位置: 首页 > news >正文

使用ReentrantLock和ThreadPoolExecutor模拟抢课

这里主要是在场景下帮助理解ReentrantLock和线程池的使用。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class GrabCourseTask implements Runnable {private final String studentName;private static int availableSeats = 10; // 假设有10个名额private static final Lock lock = new ReentrantLock(); // 创建一个ReentrantLock实例public GrabCourseTask(String studentName) {this.studentName = studentName;}@Overridepublic void run() {try {if(grabCourse()) {System.out.println(studentName + " 抢到了一个名额!");} else {System.out.println(studentName + " 没有抢到名额。");}} catch (InterruptedException e) {Thread.currentThread().interrupt();System.out.println(studentName + " 在尝试抢课时被中断。");}}private boolean grabCourse() throws InterruptedException {// 尝试获取锁if(lock.tryLock()) {try {if (availableSeats > 0) {availableSeats--; // 减少一个名额// 模拟服务器处理抢课请求需要一定的时间Thread.sleep(100);return true;}return false;} finally {lock.unlock(); // 确保在操作完成后释放锁}} else {// 如果无法立即获取锁,则表示当前有其他线程正在操作名额,直接返回失败return false;}}
}
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class CourseGrabbingSimulation {public static void main(String[] args) {// 创建线程池ThreadPoolExecutor executor = new ThreadPoolExecutor(5, // 核心线程数10, // 最大线程数1, // 空闲线程存活时间TimeUnit.SECONDS, // 时间单位new ArrayBlockingQueue<>(5)); // 任务队列// 模拟多个学生抢课for (int i = 1; i <= 15; i++) {String studentName = "学生" + i;executor.execute(new GrabCourseTask(studentName));}// 关闭线程池executor.shutdown();}
}

在真实的抢课系统中,抢课的逻辑会更加复杂,需要考虑数据库的并发访问、事务处理、网络延迟等因素。
为了简化示例,这里使用了 ReentrantLock来控制对 availableSeats 的访问,保证了线程安全。在实际应用中,可能需要更复杂的并发控制机制。

相关文章:

  • dmhs同步因目的端表自增列报错解决方法
  • 串口触摸屏的键盘控制
  • 1Mysql复习题
  • 实体类status属性使用枚举类型的步骤
  • 基于CNN的掩码自编码器微调用于分类任务
  • JS遍历数组和对象的常用方法有哪些?
  • 千益畅行,旅游卡真相,成本与赋能潜力
  • CSS打印设置页眉页脚
  • #QT(QCharts绘制曲线)
  • Dify vs Langchain:AI应用开发的全面分析
  • abstract 的 method 是否可同时是 static,是否可同时是 native,是否可同时是 synchronized?
  • SpringBoot快速入门-上
  • 用户需求分析揭秘:最佳实践与策略
  • 计算机网络——传输层重要协议(TCP、UDP)
  • ABBYY 15软件下载-ABBYY FineReader 15中文版下载附加详细安装步骤
  • Angular 4.x 动态创建组件
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • Java到底能干嘛?
  • js中的正则表达式入门
  • linux安装openssl、swoole等扩展的具体步骤
  • mockjs让前端开发独立于后端
  • Selenium实战教程系列(二)---元素定位
  • tweak 支持第三方库
  • vue脚手架vue-cli
  • 阿里研究院入选中国企业智库系统影响力榜
  • 订阅Forge Viewer所有的事件
  • 服务器之间,相同帐号,实现免密钥登录
  • 给github项目添加CI badge
  • 全栈开发——Linux
  • 手写一个CommonJS打包工具(一)
  • 我的zsh配置, 2019最新方案
  • 曾刷新两项世界纪录,腾讯优图人脸检测算法 DSFD 正式开源 ...
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • !$boo在php中什么意思,php前戏
  • #QT(TCP网络编程-服务端)
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • $forceUpdate()函数
  • (¥1011)-(一千零一拾一元整)输出
  • (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练
  • (6)STL算法之转换
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (JS基础)String 类型
  • (Oracle)SQL优化技巧(一):分页查询
  • (SpringBoot)第七章:SpringBoot日志文件
  • (三)elasticsearch 源码之启动流程分析
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (转)Unity3DUnity3D在android下调试
  • .axf 转化 .bin文件 的方法
  • .form文件_SSM框架文件上传篇
  • .NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况
  • .NET使用存储过程实现对数据库的增删改查
  • /dev下添加设备节点的方法步骤(通过device_create)
  • @DataRedisTest测试redis从未如此丝滑