线程池探索之基础篇
Posted 冥oo迹
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池探索之基础篇相关的知识,希望对你有一定的参考价值。
线程池探索之基础篇
一、使用线程池的好处
二、线程池的内部实现
三、线程池的工厂类
一、使用线程池的好处:
1)重用线程,避免系统频繁地创建和销毁线程
2)任务过多时,通过排队避免创建过多线程,减少系统资源的消耗
阿里开发手册中规定:线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
二、线程池的内部实现:
JDK中线程池的实现类是ThreadPoolExecutor,先来看看其最重要的构造方法:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
ThreadPoolExecutor类核心方法execute如下:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
ThreadPoolExecutor类的任务调度逻辑如下图:
核心代码为:
三、线程池的工厂类:
ThreadPoolExecutor类来自JDK提供的一套Executor框架,框架结构图如下:
Executor框架提供了各种类型的线程池,其内部都是通过ThreadPoolExecutor来实现的,主要有以下工厂方法:
public static ExecutorService newFixedThreadPool(int nThreads)
public static ExecutorService newSingleThreadExecutor()
public static ExecutorService newCachedThreadPool()
public static ScheduledExecutorService newSingleThreadScheduledExecutor()
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
下面来一一描述上述工厂方法:
newFixedThreadPool()方法返回一个固定线程数量的线程池。源码如下:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
newSingleThreadExecutor()方法返回一个只有一个线程的线程池。源码如下:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
newCachedThreadPool()方法返回一个核心线程数为0,最大线程数为Integer.MAX_VALUE的线程池。源码如下:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
newSingleThreadScheduledExecutor方法返回一个ScheduledExecutorService,线程池大小为1。ScheduledExecutorService是在ExecutorService的基础上增加了定时执行任务的功能。源码如下:
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
newScheduledThreadPool()方法也返回一个ScheduledExecutorService,但可指定线程池的线程数量。源码如下:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
阿里开发手册中规定:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,避免资源耗尽的风险。
Executors返回的线程池对象的弊端如下:
1) FixedThreadPool和SingleThreadPool:
允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
2) CachedThreadPool和ScheduledThreadPool:
允许创建的线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
以上是关于线程池探索之基础篇的主要内容,如果未能解决你的问题,请参考以下文章