线程池我们在前几期的web编程开发文章中已经给大家简单分析过很多次了,而今天我们就通过案例分析来了解一下,线程池实现类的定义与作用。
一:线程池的好处
1线程池可以异步的执行任务,当任务进来的时候线程池先会判断当前是否有存活可用的线程,如果有的话,线程会执行这个任务。但是任务此时可以立刻返回,并不一定必须等待任务执行完毕才会返回。假如是同步阻塞的话,当一个线程遇到Exception的时候,假如这个线程没有得到处理,那么就会造成线程堵塞,资源囤积,终的结果只能是cpu资源耗尽,所有的任务无法处理。之前我们的线上就出现了很多dubbo服务访问超时问题,后发现就是cpu资源耗尽,报了一个unabletocreatenewThread,这样就无法处理任务(后我们进行了物理扩容并且合理限定了线程池的大线程数量才解决这个问题)
2:线程池可以集中管理线程,可以控制线程的运行周期,这里包括动态添加线程或者移除线程。有一个很重要的点是这样的:线程的上下文切换是非常消耗性能的;假如来了一个任务,线程执行一次,然后立刻销毁;再来一个任务,再创建一个任务,用完再销毁这个线程。那么为什么不能对这个线程进行复用呢
3:线程池的优势只有在高请求量才会体现出来,如果请求量比较好,需要处理的任务很少,那么使用线程池的作用并不明显。但是并不是线程数量越多越好,具体的数量需要评估每个任务的处理时间以及当前计算机的处理能力和数量,这个是有具体的数据体现的。
二:线程池实现类
解释:线程池的实现类,先就是定义线程池的默认数量,为2*cpu核心数+1,这是比较合理的计算公式。小数量定义为1,大数量定义为10。还用一个LinkedList来作为工作线程的集合容器。这里为什么要用linkedList而不是ArrayList呢因为linkedList是一个双向链表,双向链表可以实现先进先出或者后进先出等集合。然后我们定义了worker来封装具体执行任务的线程,用Job来封装要执行的任务。然后在构造方法里用initWorkers方法来初始化线程池,创建指定的默认数量的线程,指定名称(用AtomicLong:原子线程安全的)并添加到管理线程的集合workers中(这个list经过synchronizedList修饰它已经成为了一个同步的集合,所做的操作都是线程安全的)。在execute中,先获取需要指定的任务(Job),为了保证线程安全,会锁住所有的任务集合(放心synchronized这个关键字的作用,它经过jdk1.7已经优化过了,性能消耗有质的提升)。这里为什么要锁住jobs这个集合呢,答案是:为了防止在多线程环境下,有多个job同时添到这个jobs里面,任务要一个个的执行,防止无法执行任务。接着再用addLast方法将任务添加到链表的后一个,这里就是一个先进先出的队列(先进入的线程会优先被执行)再调用jobs的notify方法唤醒其他job。而在下面的添加线程或者移除线程的方法,都必须要锁住整个工作队列,这里为了防止,执行的时候突然发现job不见了,或者添加的时候取不到新的job等多线程下的安全问题,并且在worker线程中增加了一个running字段,用于控制线程的运行或者停止(run方法是否执行的控制条件)
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。