Java的Executors框架提供的定长线程池内部默认使用LinkedBlockingQueue作为任务的容器,这个队列是没有限定大小的,可以无限向里面submit任务。

当线程池处理的太慢的时候,队列里的内容会积累,积累到一定程度就会内存溢出。即使没有内存溢出,队列的延迟势必会变大,而且如果进程突然遇到退出信号,队列里的消息还没有被处理就被丢弃了,那必然会对系统的消息可靠性造成重大影响。

那如何解决线程池的过饱问题呢?从队列入手,无外乎两种方法

增加消费者,增加消费者处理效率

限制生产者生产速度

增加消费者就是增加线程池大小,增加消费者处理效率就是优化逻辑处理。但是如果遇到了IO瓶颈,消费者处理的效率完全取决于IO效率,在消费能力上已经优化到了极限还是处理不过来怎么办?或者系统突然遇到用户高峰,我们所配置的线程池大小不够用怎么办?

这时候我们就只能从生产者入手,限制生产者的生产速度。那如何限制呢?

LinkedBlockingQueue提供了capacity参数可以限制队列的大小,当队列元素达到上线的时候,生产者线程会阻塞住,直到队列被消费者消费到有空槽的时候才会继续下去。这里似乎只要给队列设置一个大小就ok了。

但是实际情况并不是我们所想的那样。

翻开源码可以发现生产者向队列里塞任务用的方法是workQueue.offer(),这个方法在遇到队列满时是不会阻塞的,而是直接返回一个false,表示抛弃了这个任务。然后生产者调用reject方法,进入拒绝处理逻辑。

接下来我们看看这个reject方法到底干了什么

我们看到JDK默认提供了4中拒绝策略的实现。

AbortPolicy 默认策略,抛出RejectedExecutionException异常

CallerRunsPolicy 让任务在生产者线程里执行,这样可以降低生产者的生产速度也不会将生产者的线程堵住

DiscardPolicy 直接抛弃任务,不抛异常

DiscardOldestPolicy 直接抛弃旧任务,不抛异常

一般比较常用的是CallerRunPolicy,比较优雅的解决了过饱问题。如果你觉得这种方式不那么优雅的话,还可以使用下面的几种方式。这几种方式都是通过处理RejectExecution来实现生产者的阻塞的目的。

这种方案是使用put方法会阻塞生产者线程的原理达到了目的。

这种方案显而易见,用sleep达到了阻塞的目的。

这种方案是通过信号量的大小都限制队列的大小,也不需要特别限定executor队列大小了

同样的原理还可以使用wait/notifyAll机制来达到一样的目的。

java 队列占用内存大小_Java线程池队列吃的太饱,撑着了咋整?java 队列过大导致内存溢出...相关推荐

  1. java set和get原理_Java线程池的实现原理和使用

    为什么用线程池 在我们进行开发的时候,为了充分利用系统资源,我们通常会进行多线程开发,实现起来非常简单,需要使用线程的时候就去创建一个线程(继承Thread类.实现Runnable接口.使用Calla ...

  2. java低层源码_Java线程池及其底层源码实现分析

    */ Callable接口 && Runnable接口 callable调用call方法 runnable调用run方法 都可以被线程调用,但callable的call方法具有返回值( ...

  3. java 队列线程池_Java线程池Executor使用

    原标题:Java线程池Executor使用 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:减少系统对于,外部 服务的响应时间的等待.第 ...

  4. idea 线程内存_Java线程池系列之-Java线程池底层源码分析系列(二)

    课程简介: 课程目标:通过本课程学习,深入理解Java线程池,提升自身技术能力与价值. 适用人群:具有Java多线程基础的人群,希望深入理解线程池底层原理的人群. 课程概述:多线程的异步执行方式,虽然 ...

  5. java线程优先级队列等待_java线程池队列优先级(插队)Demo

    在做线程池操作的时候,突然来个加紧处理时,会很纠结,不知道怎么处理让加紧的线程插队先执行.该Demo使用了自定义线程池,采用优先级阻塞式队列(PriorityBlockingQueue)的方式来处理插 ...

  6. java线程不执行_java线程池,阿里为什么不允许使用Executors?

    带着问题 阿里Java代码规范为什么不允许使用Executors快速创建线程池? 下面的代码输出是什么? ThreadPoolExecutor executor = new ThreadPoolExe ...

  7. java线程池的概念_Java线程池的基本概念以及生命周期

    一.为什么要实现线程池? 线程的创建与销毁对于CPU而言开销较大,通过池化技术可避免重复的创建与销毁线程. 方便与线程资源统一管理. 二.几种常见的线程池以及核心参数 不推荐使用Executor创建线 ...

  8. java 线程执行完就会回收吗_Java线程池技术Executors的这个坑你踩过吗?

    线程池技术是Java的一大特性,如果我们想要编写高并发.高吞吐的程序,线程池的技术使用是必须的.对于很多程序员来说,多线程和线程池技术都了然于胸,基本原理和使用都数量掌握,分分钟可以写出一个生产消费者 ...

  9. java 工作池_Java线程池的工作原理,好处和注意事项

    线程池的工作原理 一个线程池管理了一组工作线程, 同时它还包括了一个用于放置等待执行 任务的任务队列(阻塞队列) . 一个线程池管理了一组工作线程, 同时它还包括了一个用于放置等待执行 任务的任务队列 ...

最新文章

  1. Array 数组去重 总结10方法(7)
  2. 我可以在Android版式中加下划线吗?
  3. SQL Server 2014 Win7 Win10 安装详解 SQL Server 2017 2019 Linux及SQL TSQL ETL实用案例
  4. js在wap端获取定位_iPhone 定位服务,没用的都关掉
  5. java pdf转base64_后台返回pdf的base64编码到前端,如果pdf中有中文,不会显示问题?...
  6. 嵌入式linux系统运行程序,嵌入式Linux系统启动过程
  7. 【系统架构】类图怎么画
  8. 百度文库文字下载(python原码)
  9. mars老师android开发视频教程5季+java4android视频教程
  10. 两波形相位差的计算值_连续模式PFC功率MOSFET电流有效值、平均值计算
  11. 域用户绑定计算机,域批量绑定用户帐户与计算机帐户
  12. RPG类型的游戏革命
  13. KFC门店定点查询(输入城市名称即可查询)
  14. 2022年7月份模拟考题解答
  15. php手绘功能,手绘之于游戏,不仅仅是一种风格
  16. imperva更改8083端口的不安全连接证书
  17. SequoiaDB v5.2 学习笔记
  18. 福布斯公布最新全球富豪排行榜 盖茨退居第二
  19. typescript常见数据结构与算法
  20. windows10操作系统家庭版,解决启用或关闭windows功能中没有Hyper-v

热门文章

  1. 人工智能与深度学习概述
  2. “设备回收”功能模块记录
  3. 快速了解 边缘计算和边缘AI
  4. OpenCV实战(15)——轮廓检测详解
  5. 小米8se android q,小米8 SE开始测试安卓Q系统, 国产第一款
  6. 个人全能服务器完美设置
  7. 【Qt】标准字体对话类
  8. 用 Java 实现人脸识别功能(附源码)
  9. python画圆及其内接多边形_Python turtle 绘图画圆(2)
  10. 华为鸿蒙系统支持电脑么,速来围观:华为鸿蒙操作系统2.0支持的设备清单流出...