什么是线程池
线程池主要解决两个问题:
1. 当执行大量异步任务时线程池能够提供较好的性能。在不使用线程池时,每当需要执行异步任务时直接new一个线程来运行,而线程的创建和销毁是需要开销的。线程池里面的线程是可复用的,不需要每次执行异步任务时都重新创建和销毁线程。
2. 线程池提供一种资源限制和管理的手段,比如可以限制线程的个数,动态新增线程等。
Java提供的4中线程池
- newFixedThreadPool(创建指定数量的线程池)
- newSingleThreadExecutor(创建单个线程的线程池)
- newCachedThreadPool(创建动态扩展的线程池)
- newScheduledThreadPool(创建延迟或定时执行的线程池)
package com.wxw.threadpool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDemo implements Runnable {
public static void main(String[] args) {
// newFixedThreadPool
//ExecutorService executorService = Executors.newFixedThreadPool(3);
// newSingleThreadExecutor
//ExecutorService executorService = Executors.newSingleThreadExecutor();
// newCachedThreadPool
//ExecutorService executorService = Executors.newCachedThreadPool();
// newScheduledThreadPool
ExecutorService executorService = Executors.newScheduledThreadPool(1);
for (int i = 0; i < 100; i++) {
executorService.execute(new ThreadPoolDemo());
}
executorService.shutdown();
}
@Override
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
线程池的深入了解
创建线程池的构造函数
public ThreadPoolExecutor(int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 超时时间,超出核心线程数量以外的线程空余存活时间
TimeUnit unit, .// 存活时间单位
BlockingQueue<Runnable> workQueue, // 保存执行任务的队列
ThreadFactory threadFactory, // 创建新线程使用的工厂
RejectedExecutionHandler handler) // 当任务无法执行的时候的处理方式
当创建指定数量的线程池(newFixedThreadPool)时的构造函数:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads, // 核心线程数与最大线程数一样
0L, TimeUnit.MILLISECONDS, // 超时时间为0,时间单位为毫秒
new LinkedBlockingQueue<Runnable>()); // 创建一个阻塞队列
}
当创建单个线程的线程池(newSingleThreadExecutor)时的构造函数:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1, // 核心线程数与最大线程数都为1
0L, TimeUnit.MILLISECONDS, // 超时时间为0,时间单位为毫秒
new LinkedBlockingQueue<Runnable>())); // 创建一个阻塞队列
}
当创建动态扩展的线程池(newCachedThreadPool)时的构造函数:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, // 核心线程数为0,最大线程数为Integer类型的最大值
60L, TimeUnit.SECONDS, // 超时时间为60,时间单位为秒
new SynchronousQueue<Runnable>()); // 创建一个同步队列
}
当创建延迟或定时执行的线程池(newScheduledThreadPool)时的构造函数:
// Executors
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
// ScheduledThreadPoolExecutor
public ScheduledThreadPoolExecutor(int corePoolSize) {
// 核心线程数为指定的数值,最大线程数为Integer类型的最大值,超时时间为0,时间单位为纳秒
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
// ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
以上4种线程池在构造时都是使用了ThreadPoolExecutor类的构造函数,只是构造时的参数不同而已。
线程池执行流程
在这里我们对原理不做深入研究,大致的流程图如下: