创建线程池的方式:
使用Java提供的用于管理线程池的接口ExecutorService 创建线程池,共有四种方式:
Executors.newCachedThreadPool();
Executors.newFixedThreadPool(10);
Executors.newScheduledThreadPool(10);
Executors.newSingleThreadExecutor();
// 获取当前主机的处理器cpu的可用个数,可根据该参数来修改线程池的大小
System.out.println("处理器的可用个数:" + Runtime.getRuntime().availableProcessors());
1、 newCachedThreadPool
创建一个可根据需要创建新线程的线程池,在以前创建的线程可用时重用它们。该线程池可缓存,无限大。
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
}
});
}
}
源码:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
// 上面返回的对象指向下面的 ThreadPoolExecutor(...) 构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
参数的意义:
- corePoolSize :核心线程池的数量
- maximumPoolSize :线程池的最大数量, Integer.MAX_VALUE 可以看作是无限的
- keepAliveTime : 线程保持活跃状态的时间
- unit : 时间单位
- workQueue : 工作队列,SynchronousQueue 是一个不存储元素的队列,可以理解为队列已满
根据上面的源码可知:
当调用该方法创建线程池时,workQueue 为0,不创建核心线程,且队列已满,因此会创建非核心线程执行任务。对于非核心线程空闲60s就会被回收,而线程池的数量几乎是无限的,当资源有限时易引起OOM异常。
2、newFixedThreadPool
创建一个可重用固定线程集合的线程池,以共享的无界队列方式运行线程。
定长的线程池,可控制线程最大并发数,超出的线程会在队列中等待。
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
}
});
}
}
源码:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
// 上面返回的对象指向下面的 ThreadPoolExecutor(...) 构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
说明
参数与SingleThreadExecutor 一致,区别是核心线程数是由用户传入的。
3、newSingleThreadExecutor
创建一个使用单个worker线程的线程池,以无界队列的方式运行。
该线程池只存在一个线程,会按照顺序执行,不同与单线程。
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
}
});
}
}
源码:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
// 上面返回的对象指向下面的 ThreadPoolExecutor(...) 构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
说明
返回的核心线程池数量为1,最大线程池数量为1,即只能创建一个非核心线程。
4、newScheduledThreadPool
创建一个线程池,可安排在给定延迟后运行命令或定期执行。
定长线的程池,支持定时及周期性任务执行。
public static void main(String[] args) {
ExecutorService executorService = Executors.newScheduledThreadPool(10);
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
}
});
}
}
源码:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
// 上面返回的对象指向下面的构造方法
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
// 查看ScheduledThreadPoolExecutor 的类,发现其继承了ThreadPoolExecutor,并实现了ScheduledExecutorService接口
public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService {...}
// 继续追踪父类的构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
// this(...)方法对应的如下:
public ThreadPoolExecutor(int corePoolSize, // 核心线程池数量
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 保持线程存活时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 保存任务的阻塞队列
ThreadFactory threadFactory, // 创建线程的工厂
RejectedExecutionHandler handler) { // 拒接策略
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
其他方式
// 通过ScheduledExecutorService(继承了ExecutorService)接口,调用schedule方法,通过该方法中的参数设置可以设置执行时间。
// 该方法的第二个、第三个参数结合设置从当前开始推迟设置的时间来执行
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 10; i++) {
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
}
}, 3, TimeUnit.SECONDS);
}
}