如何设置线程池会比较合理?
在不同的并发和执行耗时场景下,我们如何设置我们的线程池会更加合理呢?
高并发,低耗时
建议少线程,只要满足并发即可;例如并发100,线程池可能设置为10就可以。如果线程太多,有可能出现线程切换和管理的时间,大于任务执行的时间,那效率就低了。
低并发,高耗时
建议多线程,保证有空闲线程,接受新的任务;例如并发10,线程池可能就要设置为20;
高并发,高耗时
要分析任务类型,增加排队,加大线程数
单例模式下的高并发线程池处理
在很多场景都会遇到高并发情况:"短时间内遇到大量操作请求"。主要发生在web系统集中大量访问或者socket端口集中性收到大量请求。该情况的发生会导致系统在这段时间内执行大量操作,例如对资源的请求,数据库的操作等。处理不好,可能导致系统宕机,严重的甚至导致OOM异常,系统停止工作等。
实际工作,我们可以使用线程池技术作为处理高并发的手段之一,解决部分问题。
比如:查询推荐商品数据接口,请求此接口访问高并发,并且接口返回数据时间长,在这种高并发的情况下不使用线程池:
可能造成系统创建大量线程而导致消耗完系统内存以及”过度切换”(1W请求同时执行,创建1W线程),导致宕机。
接口查询速度本身就慢,又同时访问对数据库服务器造成很大的压力。
如果使用线程池,能解决以下问题:
有效的降低了线程创建释放的时间花销及资源开销。
有效控制最大并发线程数,降低了同时请求数(线程池设置线程数量上限,超过则排队等候)。
充分重复利用线程。
controller 是单例模式还是多例模式
springmvc controller默认的是单例singleton的,单例模式是spring推荐的配置,它在高并发下能极大的节省资源,提高服务抗压能力。采用单例模式的好处:
为了性能,单例不用每次都new,当然快了。
不需要多例,这是官方说法。
单例模式下容易出现的问题就是controller中定义很多的属性,那么单例肯定会出现竞争访问,不同用户共享数据变量是不安全的。因此:
不要在controller中定义成员变量。
万一必须要定义一个非静态成员变量时候,则通过注解@Scope("prototype"),将其设置为多例模式。
在Controller中使用ThreadLocal变量
当然可以修改controller 为多列模式,通过@controller之前增加@Scope("prototype"),或者配置文件定义修改。
Struts2默认的实现是Prototype模式,Struts2中的Action因为会有User、BizEntity这样的实例对象,是有状态信息的,在多线程环境下是不安全的,所以是多例。