淮南制作网站app手机网站模板免费下载

张小明 2026/1/10 9:44:15
淮南制作网站,app手机网站模板免费下载,qq小程序怎么关闭,wordpress登录不了引言 大家好#xff0c;我是小码#xff0c;一个在Java开发路上摸爬滚打的研二学生。最近在优化我们那个大营销抽奖系统时#xff0c;频繁遇到了线程管理的问题——内存溢出、响应变慢、甚至服务直接挂掉。痛定思痛#xff0c;我花了整整一周时间重新梳理了Java线程池的方方…引言大家好我是小码一个在Java开发路上摸爬滚打的研二学生。最近在优化我们那个大营销抽奖系统时频繁遇到了线程管理的问题——内存溢出、响应变慢、甚至服务直接挂掉。痛定思痛我花了整整一周时间重新梳理了Java线程池的方方面面。今天这篇文章就是把我踩过的坑和总结的经验分享给大家希望能帮你少走弯路真正掌握线程池这个并发编程的利器。一、为什么必须用线程池先说说我遇到的真实场景。在用户增长营销活动中我们需要同时处理成千上万的抽奖请求。最初我们很天真每个请求都new Thread()结果活动上线10分钟服务器就扛不住了。不用线程池的三大痛点资源消耗巨大创建/销毁线程开销大JVM频繁GC稳定性差无限制创建线程会导致OOMOutOfMemoryError管理困难无法统一监控、调优线程状态// 错误示范为每个任务创建新线程 public void handleLotteryRequest(UserRequest request) { new Thread(() - { // 抽奖业务逻辑 doLottery(request); }).start(); // 问题瞬间10000个请求就创建10000个线程 } // 正确做法使用线程池 private ExecutorService executor Executors.newFixedThreadPool(10); public void handleLotteryRequest(UserRequest request) { executor.submit(() - { doLottery(request); }); }二、ThreadPoolExecutor的七大核心参数要真正玩转线程池必须深入理解ThreadPoolExecutor的构造参数。这是面试必考点更是实际调优的关键。public ThreadPoolExecutor( int corePoolSize, // 核心线程数 int maximumPoolSize, // 最大线程数 long keepAliveTime, // 空闲线程存活时间 TimeUnit unit, // 时间单位 BlockingQueueRunnable workQueue, // 工作队列 ThreadFactory threadFactory, // 线程工厂 RejectedExecutionHandler handler // 拒绝策略 )2.1 核心参数详解1. corePoolSize核心线程数作用线程池中常驻的核心线程数量特点即使线程空闲也不会被回收除非设置allowCoreThreadTimeOut设置建议CPU密集型任务CPU核数1IO密集型任务CPU核数 * 2// 获取CPU核数 int cpuCores Runtime.getRuntime().availableProcessors(); // CPU密集型任务配置 int corePoolSize cpuCores 1; // IO密集型任务配置如网络请求、数据库操作 int ioCorePoolSize cpuCores * 2;2. maximumPoolSize最大线程数作用线程池允许创建的最大线程数量触发条件当工作队列满了且当前线程数 maximumPoolSize时经验值一般设置为corePoolSize的2-3倍3. workQueue工作队列这是最容易出问题的地方队列选择直接影响系统行为| 队列类型 | 特点 | 适用场景 | |---------|------|---------| | SynchronousQueue | 不存储元素直接传递 | 高并发、任务处理快 | | ArrayBlockingQueue | 有界队列FIFO | 需要控制队列长度 | | LinkedBlockingQueue | 无界队列默认Integer.MAX_VALUE | 任务量波动大 | | PriorityBlockingQueue | 优先级队列 | 任务有优先级区分 |血泪教训在抽奖系统中我们最初用了无界队列结果内存飙升。后来改用有界队列合适的拒绝策略系统稳定多了。4. 拒绝策略4种内置策略当队列满了且线程数达到maximumPoolSize时新任务如何处理// 1. AbortPolicy默认直接抛出异常 new ThreadPoolExecutor.AbortPolicy(); // 2. CallerRunsPolicy由调用者线程执行 // 适合不希望任务丢失可以接受调用线程变慢 new ThreadPoolExecutor.CallerRunsPolicy(); // 3. DiscardPolicy直接丢弃任务不抛异常 // 风险任务静默丢失不易发现问题 new ThreadPoolExecutor.DiscardPolicy(); // 4. DiscardOldestPolicy丢弃队列中最老的任务 // 适合最新任务比老任务更重要 new ThreadPoolExecutor.DiscardOldestPolicy();实战建议在电商大促场景我们自定义了拒绝策略把拒绝的任务存入Redis等高峰过后再处理。三、四种预定义线程池的坑Java提供了4种快捷创建方式但生产环境要慎用3.1 FixedThreadPool - 固定大小线程池// 看似美好实则暗藏风险 ExecutorService executor Executors.newFixedThreadPool(10);问题使用无界队列LinkedBlockingQueue任务堆积可能导致OOM3.2 CachedThreadPool - 缓存线程池// 线程数几乎无限制非常危险 ExecutorService executor Executors.newCachedThreadPool();问题maximumPoolSize为Integer.MAX_VALUE高并发时创建大量线程3.3 SingleThreadExecutor - 单线程线程池// 保证顺序执行但队列无界 ExecutorService executor Executors.newSingleThreadExecutor();3.4 ScheduledThreadPool - 定时任务线程池// 同样有无界队列问题 ScheduledExecutorService executor Executors.newScheduledThreadPool(5);结论阿里Java开发规范明确禁止使用Executors创建线程池必须手动创建ThreadPoolExecutor四、实战营销系统线程池配置方案下面是我们抽奖系统最终采用的线程池配置方案Component public class LotteryThreadPoolConfig { /** * 抽奖核心业务线程池 * 特点快速响应队列不宜过长 */ Bean(lotteryCoreExecutor) public ThreadPoolExecutor lotteryCoreExecutor() { int cpuCores Runtime.getRuntime().availableProcessors(); return new ThreadPoolExecutor( cpuCores * 2, // 核心线程IO密集型 cpuCores * 4, // 最大线程 60L, TimeUnit.SECONDS, // 空闲60秒回收 new ArrayBlockingQueue(1000), // 有界队列防止OOM new NamedThreadFactory(lottery-core), // 自定义线程工厂 new LotteryRejectHandler() // 自定义拒绝策略 ); } /** * 异步记录日志线程池 * 特点允许一定延迟队列可以稍大 */ Bean(logExecutor) public ThreadPoolExecutor logExecutor() { return new ThreadPoolExecutor( 2, // 核心线程数少 5, // 最大线程数少 120L, TimeUnit.SECONDS, // 空闲时间长 new LinkedBlockingQueue(5000), // 队列较大 new NamedThreadFactory(log-executor), new ThreadPoolExecutor.DiscardOldestPolicy() // 丢弃最老日志 ); } } /** * 自定义线程工厂便于问题排查 */ class NamedThreadFactory implements ThreadFactory { private final String namePrefix; private final AtomicInteger threadNumber new AtomicInteger(1); NamedThreadFactory(String poolName) { namePrefix poolName -thread-; } Override public Thread newThread(Runnable r) { Thread t new Thread(r, namePrefix threadNumber.getAndIncrement()); // 设置为非守护线程 t.setDaemon(false); // 设置合理优先级 t.setPriority(Thread.NORM_PRIORITY); return t; } } /** * 自定义拒绝策略记录日志并降级处理 */ class LotteryRejectHandler implements RejectedExecutionHandler { private static final Logger logger LoggerFactory.getLogger(LotteryRejectHandler.class); Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // 记录被拒绝的任务 logger.warn(任务被拒绝线程池状态活跃线程{}, 队列大小{}, 已完成任务{}, executor.getActiveCount(), executor.getQueue().size(), executor.getCompletedTaskCount()); // 降级方案存入Redis后续补偿处理 if (r instanceof LotteryTask) { LotteryTask task (LotteryTask) r; redisTemplate.opsForList().rightPush(lottery:rejected:tasks, task); logger.info(任务已存入Redis等待补偿处理任务ID{}, task.getTaskId()); } } }五、监控与调优技巧5.1 如何监控线程池状态Component Slf4j public class ThreadPoolMonitor { Autowired private ThreadPoolExecutor lotteryCoreExecutor; Scheduled(fixedRate 30000) // 每30秒监控一次 public void monitor() { log.info( 线程池监控报告 ); log.info(核心线程数: {}, lotteryCoreExecutor.getCorePoolSize()); log.info(活跃线程数: {}, lotteryCoreExecutor.getActiveCount()); log.info(最大线程数: {}, lotteryCoreExecutor.getMaximumPoolSize()); log.info(队列大小: {}/{}, lotteryCoreExecutor.getQueue().size(), lotteryCoreExecutor.getQueue().remainingCapacity()); log.info(完成任务数: {}, lotteryCoreExecutor.getCompletedTaskCount()); // 计算队列使用率 double queueUsage (double) lotteryCoreExecutor.getQueue().size() / (lotteryCoreExecutor.getQueue().size() lotteryCoreExecutor.getQueue().remainingCapacity()); if (queueUsage 0.8) { log.warn(队列使用率过高: {}%, queueUsage * 100); } } }5.2 动态调整线程池参数在Spring环境中我们可以动态调整线程池参数RestController RequestMapping(/threadpool) public class ThreadPoolController { Autowired private ThreadPoolExecutor lotteryCoreExecutor; /** * 动态修改核心线程数 */ PostMapping(/adjust) public String adjustCorePoolSize(RequestParam int newCoreSize) { if (newCoreSize lotteryCoreExecutor.getMaximumPoolSize()) { lotteryCoreExecutor.setCorePoolSize(newCoreSize); return 核心线程数已调整为: newCoreSize; } return 核心线程数不能大于最大线程数; } /** * 获取线程池状态 */ GetMapping(/status) public MapString, Object getStatus() { MapString, Object status new HashMap(); status.put(corePoolSize, lotteryCoreExecutor.getCorePoolSize()); status.put(activeCount, lotteryCoreExecutor.getActiveCount()); status.put(poolSize, lotteryCoreExecutor.getPoolSize()); status.put(queueSize, lotteryCoreExecutor.getQueue().size()); status.put(completedTaskCount, lotteryCoreExecutor.getCompletedTaskCount()); return status; } }六、常见问题与解决方案问题1线程池中的线程异常消失怎么办executor.submit(() - { try { // 业务代码 doBusiness(); } catch (Exception e) { // 必须捕获异常否则异常会被吞掉 log.error(任务执行异常, e); // 根据业务决定是否重试 if (shouldRetry()) { retryTask(); } } }); // 或者使用Future获取异常 Future? future executor.submit(task); try { future.get(); } catch (ExecutionException e) { // 这里能拿到任务中的异常 Throwable cause e.getCause(); log.error(任务执行失败, cause); }问题2如何优雅关闭线程池Component public class ThreadPoolShutdown implements DisposableBean { Autowired private ThreadPoolExecutor lotteryCoreExecutor; Override public void destroy() throws Exception { shutdownGracefully(lotteryCoreExecutor, 抽奖线程池); } private void shutdownGracefully(ExecutorService executor, String poolName) { log.info(开始关闭{}..., poolName); // 1. 停止接收新任务 executor.shutdown(); try { // 2. 等待现有任务完成最多等30秒 if (!executor.awaitTermination(30, TimeUnit.SECONDS)) { log.warn({}等待超时尝试强制关闭, poolName); // 3. 尝试取消所有任务 executor.shutdownNow(); // 4. 再等待一段时间 if (!executor.awaitTermination(10, TimeUnit.SECONDS)) { log.error({}未能正常关闭, poolName); } } } catch (InterruptedException e) { // 重新尝试强制关闭 executor.shutdownNow(); Thread.currentThread().interrupt(); } log.info({}已关闭, poolName); } }总结线程池用好了是利器用不好就是坑。关键记住三点第一永远不要用Executors的快捷方法要手动创建ThreadPoolExecutor第二合理配置核心参数特别是队列一定要用有界的第三做好监控和优雅关闭线上问题早发现早处理。把这些掌握了你的并发编程水平就能上一个台阶。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

lamp 网站建设论文哪做网站

在Google搜索结果中占据Featured Snippets(精选摘要)位置,意味着获得平均35.2%的点击率提升(据Ahrefs 2024年数据)。但大多数企业仍在使用传统SEO策略,错失这一黄金展示位。本文将基于水滴互动服务的500企业…

张小明 2026/1/7 7:56:02 网站建设

网页设计的网网页设计的网站建设一篇网站设计小结

在数字化转型浪潮中,测试开发工程师的角色已从单纯的"缺陷发现者"演变为"质量守护与效能推动者"。面对DevOps普及、云原生架构兴起和AI测试工具泛化的2025年技术环境,测试开发工程师需要构建独特的核心竞争力体系。本文将从技术能力…

张小明 2026/1/7 19:11:08 网站建设

如何做一张旅游网站做旅游的网站 优帮云

Jessibuca Pro完整教程:Web流媒体播放器终极指南 【免费下载链接】jessibuca Jessibuca是一款开源的纯H5直播流播放器 项目地址: https://gitcode.com/GitHub_Trending/je/jessibuca Jessibuca Pro作为一款专业的Web流媒体播放器,凭借其强大的多协…

张小明 2026/1/7 17:42:21 网站建设

河北哪些大学网站建设专业比较好网店网站源码

大学校园失物招领系统的背景与需求随着移动互联网技术的普及和高校信息化建设的推进,校园生活场景中的物品遗失问题逐渐凸显。学生在校园内丢失物品(如校园卡、钥匙、书包、电子设备等)或拾获他人失物时,传统的信息传递方式&#…

张小明 2026/1/4 22:54:51 网站建设

网站工程师简历全球网站排行榜

FF14终极插件框架:Dalamud完整开发指南与实战应用 【免费下载链接】Dalamud FFXIV plugin framework and API 项目地址: https://gitcode.com/GitHub_Trending/da/Dalamud 还在为《最终幻想XIV》中繁琐的操作界面和缺失的功能而苦恼吗?Dalamud插件…

张小明 2026/1/4 22:54:44 网站建设

谷歌做自己的网站12数据网站建设

深度学习模型推理加速:从原型到生产的3倍性能提升方案 【免费下载链接】DAIN Depth-Aware Video Frame Interpolation (CVPR 2019) 项目地址: https://gitcode.com/gh_mirrors/da/DAIN 你是否还在为深度学习模型在部署时的性能瓶颈而困扰?训练时表…

张小明 2026/1/5 16:12:13 网站建设