每日一省:对于读过的好的技术博客,要懂得总结归纳,消化吸收,才能在需要用到的时候心中有数,甚至信手拈来。
今天看到的比较好的一篇关于java的线程池的博客,写下观后感。
首先是使用线程池的好处:
- 线程池里面,线程可以进行复用,从而减少线程的创建和销毁,因此可以减少线程创建和销毁的开销,提高cpu的使用率。
- 线程池可以管理线程数量,这样有两个好处:一是可以防止因为创建的线程过多而导致占用太多内存造成线程拥堵甚至导致oom系统错误。(每个线程大概占用1MB的内存空间)二是可以合理控制线程的数量,线程池里面会使用一些策略,在当前请求较多时,适当的增加线程的数量,保证吞吐量,而在请求比较少的时候,适当的销毁线程或者使线程处于空闲状态,把系统资源释放出来给其他需要的地方使用,以保证系统的利用率。
- 线程池里面还会内置一些方法可供调用,比如定时任务。
有了上面说的这些优点,因此在程序里面应该尽量去使用线程池。
java提供了以下5种内置的线程池,具体每个方法的说明是参考网上的博客,自己还没有去看过源代码:
- newCachedThreadPool,创建一个可缓存线程池,其特性是,线程数量上限可以说是无限大(达到整数的最大值0x7fffffff),使用的队列是SynchronousQueue,这种队列是没有存储空间的,一旦有新的任务进来,就必须马上分配(创建)一个新的线程去执行,另外线程的keepAliveTime为60S,空闲时间超过60s的话,该线程就会被销毁。这种特性的线程池,比较适合用于需要创建数量比较多的运行时间比较短的线程的场景。使用这种线程池的时候要注意,因为该池子是不会拒绝任务的,如果线程池处理任务的速度赶不上提交的任务的速度,那么就会不断的创建新线程,直到耗尽内存导致oom错误,所以必须要保证提交任务的速度不能快过处理速度。
- newFixedThreadPool,创建指定数量的线程,keepAliveTime为0,用完即刻销毁线程,使用的队列是LinkedBlockingQueue
- newScheduledThreadPool,可以指定核心线程数量corePoolSize,数量没有上限,这个线程可以设置线程延时启动以及定时执行任务
- newSingleThreadExecutor,单个线程,用完即毁,使用的队列是LinkedBlockingQueue
- newSingleThreadScheduledExecutor,核心线程只有1个,非核心线程数量可以有无数个,使用的队列是DelayedWorkQueue,也就是具备延时和定时器的功能。
实际上上面的这些方法都是调用的ThreadPoolExecutor构造方法,然后根据我们传入的参数去设置对应的变量值,因此如果以上的5个方法都无法满足要求时,我们可以直接调用ThreadPoolExecutor构造方法去自定义自己的线程池。
疑问:上面几个java内置的创建线程池的方法,有些使用了无上限的队列,有些又没有限制创建的线程数量上限,这样请求太多太快的话有可能会导致oom问题。
这里只是记载一下,源码没看,先把详细介绍的博客贴上,以便以后复习: Java并发编程:线程池的使用
还有一篇知乎的专栏,介绍了使用这几个线程池的坑:
一次Java线程池误用引发的血案和总结
网友评论