JAVA业务开发常见错误整理(3.线程池 4.连接池)

朱晔《Java业务开发常见错误100例》课程学习整理

 

一、线程池

线程池的声明需要手动进行

《阿里巴巴Java开发手册》中提到。禁止使用Java中的Executors类定义的快捷工具方法,而应该手动new ThreadPoolExecutor来创建线程池。最典型的问题就是new FixedThreadPool和new CachedThreadPool,可能因为资源耗尽导致OOM问题。

(1)new FixedThreadPool时,线程池的工作队列直接new了一个LinkedBlockingQuene,而默认构造方法的LinkedBlockingQueue是一个Integer.MAX_VALUE长度的队列,基本可以认为无界,因此即使工作线程是固定的,但任务队列是无界的。如果任务多且执行慢,队列快速挤压撑爆内存则会导致OOM

(2) new CacheThreadPool时,线程池的最大线程数是Integer.MAX_VALUE,基本可以认为无界,而其工作队列SynchronousQueue是一个没有存储空间的阻塞队列。因此线程池需要为每一个任务分配一条工作线程处理,没有空闲线程则需在创建新的,如果任务多且执行慢,则需要创建大量的线程,而线程是需要内存空间作为线程栈的,无限制创建线程必然会导致OOM

此外不建议使用Executors提供的两种快捷的线程池还有以下原因:

我们需要根据自己的场景、并发情况来评估线程池的几个核心参数

线程池线程管理策略

线程池默认工作行为

(1) 不会初始化corePoolSize个线程,有任务需执行才创建工作线程

(2)核心线程满了之后不会立即扩容线程池,而是把任务堆积到工作队列中

(3)当工作队列满了后扩容线程池,直到线程个数达到maximumPoolSize

(4)如果队列已满且达到最大线程后还有任务,则按照拒绝策略处理

(5)当线程数大于核心线程数时,线程等待keepAliveTime后还没有任务需要处理,收缩线程到核心线程数

 

二、连接池

业务项目常用连接池:数据库连接池、Redis连接池、HTTP连接池

鉴别客户端SDK是否基于连接池

TCP是面向连接的基于字节流的协议

(1)面向链接,意味着连接需要先创建再使用,创建连接的三次握手有一定开销

(2)基于字节流,意味着字节是发送数据的最小单元,TCP协议本身无法区分哪几个字节是完整的消息体,也无法感知是否有多个客户端在使用同一个TCP连接,TCP只是一个读写数据的管道

客户端SDK没有使用连接池,而是TCP连接,则需要考虑每次建立TCP连接的开销,并且因为TCP给予字节流,在多线程的情况下对同一连接复用,可能产生线程安全问题

TCP连接客户端SDK对外提供API的三种方式,以及最佳实践:

(1)连接池和连接分离的API,连接池本身一般是线程安全的,可以服用。每次使用需要从连接池获取连接,使用后归还,归还的工作由使用者负责

(2)内置连接池,SDK会负责连接的获取和归还,使用的时候直接复用客户端。

(3)如果SDK没有实现连接池(大多数中间件、数据库的客户端都会支持连接池),通常不是线程安全的,而且短连接的方式性能不高,使用的时候需考虑自己封装连接池

Jedis分析

我们在多线程环境下复用Jedis,其实就是在复用RedisOutputStream。如果多个线程在执行操作,那么既无法确保整条命令以原子操作写入Socket,也无法确保写入后、读取前没有其他数据写到远端

解决办法,使用Jedis提供的线程安全类JedisPool获得Jedis实例。JedisPool可以声明为static再多个线程之间贡献,扮演连接池的角色。使用时,以try-with-resources模式从JedisPool获得和归还Jedis实例。

SpringBoot在启动过程中,刷新Context后,如果registerShutdownHook开始(默认为true),则会注册Shutdown Hook,提供Spring Shutdown Hook能力的是spring-context,即spring framework本身的能力,但是将shutdown hook注册进JVM shutdown hook的行为是Springboot Boot提供的。即如果在纯Spring环境下,需要手动调用注册shutdown hook来支持Spring的优雅关闭

使用连接池务必确保复用

池一定是用来复用的,否则其使用代价会比每次创建单一对象更大,对连接池来说更是如此

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值