一、线程池的概念
线程池,顾名思义就是一个维护了好多线程的“池子”,因为new一个Thread是很消耗资源的,销毁一个线程也是很费资源的,如果能把一些线程维护起来,重复利用(用的时候去线程池里直接去一条闲置的线程),那么将会大大的节约消耗。
大白话:new Thread()创建线程和销毁线程很费资源,线程池的作用就是维护若干线程,用的时候去线程池里取出线程,该线程完成工作后并不销毁,而是继续维护在线程池中,等待下次的复用。
二、线程池阻塞队列(简单讲解):
首先,线程池的阻塞队列常用以下几种:LinkedBlockingDeque,LinkedBlockingQueue,SynchronousQueue。
LinkedBlockingDeque/LinkedBlockingQueue:队列的大小可以决定有多少个正在排队的任务,超过的将会被拒绝。
SynchronousQueue无队列,超过最大线程数直接拒绝任务。
说的比较简单,更多详细的讲解可以自行在网上搜搜,因为本篇博客主要讲解线程池,所以这里暂时只知道这些就够用了。
三、线程池的简单创建:
创建简单的线程池有以下几种方法:
ExecutorService service = Executors.newCachedThreadPool();
ExecutorService service = Executors.newFixedThreadPool(3);
ExecutorService service = Executors.newSingleThreadExecutor();
其实还有一个:newScheduledThreadPool,这个是延时执行的线程池,可以用来代替Timer定时器,因为篇幅有限,这里先不写了,回头我会单独写一篇博客讲解一下。
Java并发编程——线程池的使用(五)延时执行的线程池ScheduledExecutorService
下面来说说几种线程池的不同:
3.1 newCachedThreadPool
ExecutorService service = Executors.newCachedThreadPool();
创建一个可缓存的线程池,理论上县城并没有限制,看下newCachedThreadPool的源码:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
标红的文字是指线程最大的数量,取得是整形的最大值,所以在使用这种方式创建线程池的时候,一定要控制好任务的最大数量,否则系统可能会瘫痪。SynchronousQueue的作用会在后面的文子中讲解。
3.2 newFixedThreadPool(num)
ExecutorService service = Executors.newFixedThreadPool(3);
例如这是创建一个维护了三条线程的线程池,当任务数量超过线程池维护的线程数量时,会把任务添加到队列中,依次执行。看下源码:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
3.3 newSingleThreadExecutor()
ExecutorService service = Executors.newSingleThreadExecutor();
该方法创建的线程池只有一条线程:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}