线程池的好处
因为多线程是异步执行,加快速度,但是线程创建过多,反而会造成内存占有过多。为了避免过多创建的线程,创建线程池管理线程
线程池的创建
- Executors.newCachedThreadPool():无限线程池。
源码介绍:Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks.
1
2
3
4
5 public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
- Executors.newFixedThreadPool(nThreads):创建固定大小的线程池。
源码介绍:Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most {@code nThreads} threads will be active processing tasks.If additional tasks are submitted when all threads are active,
they will wait in the queue until a thread is available.
1
2
3
4
5 public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
- Executors.newSingleThreadExecutor():创建单个线程的线程池。
源码介绍:Creates an Executor that uses a single worker thread operating
off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.)
1 | public static ExecutorService newSingleThreadExecutor() { |
发现都是通过ThreadPoolExecutor创建的:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
ThreadPoolExecutor
有四个构造函数(含有个多个参数)
int corePoolSize => 该线程池中核心线程数最大值
int maximumPoolSize 线程总数最大值
long keepAliveTime 非核心线程闲置超时时长
TimeUnit unit keepAliveTime的单位
BlockingQueue workQueue 维护着等待执行的Runnable对象
ThreadFactory threadFactory 创建线程的方式
RejectedExecutionHandler handler抛异常
线程池的执行流程
- 线程数量未达到线程池核心线程最大数,则新建一个线程(核心线程)执行任务
- 线程数量达到了线程池核心线程最大数,则将任务移入队列等待
- 队列未满,将任务存在队列中
- 队列已满,正在运行的线程数量小于线程总数,还会继续创建线程
- 队列已满,正在运行的线程数量大于等于线程总数,就会通过策略进行后续任务的处理
线程池的饱和策略
ThreadPoolExecutor的饱和策略通过调用setRejectedExecutionHandler来修改
- AbortPolicy
这个是java线程池默认的阻塞策略,不执行此任务,而且直接抛出一个运行时异常- DiscardPolicy
直接抛弃,任务不执行,空方法- DiscardOldestPolicy
从队列里面抛弃head的一个任务,并再次execute 此task。- CallerRunsPolicy
在调用execute的线程里面执行此command,会阻塞入口
例如:1
2
3
4
ThreadPoolExecutor executor=new ThreadPoolExecutor(N_THREADS,N_THREADS,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(CAPACITY));
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());