开发中你是否在用线程的时候一味的在new,这是很明显的弊端使用,项目中会有太多的地方需要线程,当你new了无数个线程时:
1.每次new Thread新建对象性能差
- 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,即可能占用过多的系统资源导致死机(OOM)
3.缺乏更多功能,比如定时执行,定期执行,线程中断
二:## 线程池 ThreadPoolExecutor
在 Java中 线程池的顶级接口 Executor这个接口。而Executor也也为我们创建了不同的线程池,想了解的小伙伴可以重点看下这个类。下面我们主要说的是ThreadPoolExecutor 类:
-首先看下它的构造函数:
五个参数:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
}
六个参数:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
//六个参数的构造函数-2
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
//七个参数的构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
-
其次让我们看下这些参数代表的意思:
-
corePoolSize:线程池中的核心线程最大数。
补充:核心线程:当线程池新建线程时候,若当前线程数小于corePoolSize,则创建的线程为核心线程。若超过则新建的为非核心线程。核心线程默认情况下会一直存活在线程池中,即使这个核心线程啥也不干(闲置状态)
你如果看注释的话你发现还有一句话,如果指定的 ThreadPoolExecutor 的allowCoreThreadTimeOut 属性为true.那么核心线程如果闲置状态,超过一定时长(可设置),就会被销毁掉。 -
int maximumPoolSize
线程池中线程总数的最大值
线程总数=核心线程+非核心线程 -
long keepAliveTime
线程池中非核心线程闲置超时时长。
倘若设置allowCoreThreadTimeout=ture,则会作用于核心线程。 -
TimeUnit unit
keepAliveTime的单位,TimeUnit是一个枚举类型,其包括:NANOSECONDS : 1微毫秒 = 1微秒 / 1000
MICROSECONDS : 1微秒 = 1毫秒 / 1000
MILLISECONDS : 1毫秒 = 1秒 /1000
SECONDS : 秒
MINUTES : 分
HOURS : 小时
DAYS : 天 -
BlockingQueue workQueue
线程池中的任务队列:维护着等待执行的Runnable对象 当所有的核心线程都在干活时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务
补充:
常用的workQueue类型:
1:SynchronousQueue:这个队列接收到任务的时候,会直接提交给线程处理,而不保留它,如果所有线程都在工作怎么办?那就新建一个线程来处理这个任务!所以为了保证不出现<线程数达到了maximumPoolSize而不能新建线程>的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE,即无限大
:2:LinkedBlockingQueue:这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize
3:ArrayBlockingQueue:可以限定队列的长度,接收到任务的时候,如果没有达到corePoolSize的值,则新建线程(核心线程)执行任务,如果达到了,则入队等候,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误
4:DelayQueue:队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务
RejectedExecutionHandler handler
,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误。
会有一个默认的。
以上就是各参数的大体意思。接下来我们对ThreadPoolExecutor这个类做一下封装处理,方便我们调用:
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 功能:线程池
* 作者: YPU
* 日期: 2019/6/23
* 时间: 13:23
*/
public class ThreadManager {
public static final String DEFAULT_SINGLE_POOL_NAME = "DEFAULT_SINGLE_POOL_NAME";
private static ThreadPoolProxy mLongPool = null;
private static Object mLongLock = new Object();
private static ThreadPoolProxy mShortPool = null;
private static Object mShortLock = new Object();
private static ThreadPoolProxy mDownloadPool = null;
private static Object mDownloadLock = new Object();
private static Map<String, ThreadPoolProxy> mMap = new HashMap<String, ThreadPoolProxy>();
private static Object mSingleLock = new Object();
//==========================================================================
// 构造方法
//==========================================================================
//==========================================================================
// get、set方法
//==========================================================================
/**
* 获取下载线程
*/
public static ThreadPoolProxy getDownloadPool() {
synchronized (mDownloadLock) {
if (mDownloadPool == null) {
mDownloadPool = new ThreadPoolProxy(3, 3, 5L);
}
return mDownloadPool;
}
}
/**
* 获取一个用于执行长耗时任务的线程池,避免和短耗时任务处在同一个队列而阻塞了重要的短耗时任务,通常用来联网操作
*/
public static ThreadPoolProxy getLongPool() {
synchronized (mLongLock) {
if (mLongPool == null) {
mLongPool = new ThreadPoolProxy(5, 5, 5L);
}
return mLongPool;
}
}
/**
* 获取一个用于执行短耗时任务的线程池,避免因为和耗时长的任务处在同一个队列而长时间得不到执行,通常用来执行本地的IO/SQL
*/
public static ThreadPoolProxy getShortPool() {
synchronized (mShortLock) {
if (mShortPool == null) {
mShortPool = new ThreadPoolProxy(2, 2, 5L);
}
return mShortPool;
}
}
/**
* 获取一个单线程池,所有任务将会被按照加入的顺序执行,免除了同步开销的问题
*/
public static ThreadPoolProxy getSinglePool() {
return getSinglePool(DEFAULT_SINGLE_POOL_NAME);
}
/**
* 获取一个单线程池,所有任务将会被按照加入的顺序执行,免除了同步开销的问题
*/
public static ThreadPoolProxy getSinglePool(String name) {
synchronized (mSingleLock) {
ThreadPoolProxy singlePool = mMap.get(name);
if (singlePool == null) {
singlePool = new ThreadPoolProxy(1, 1, 5L);
mMap.put(name, singlePool);
}
return singlePool;
}
}
//==========================================================================
// 内部类、内部接口
//==========================================================================
public static class ThreadPoolProxy {
private ThreadPoolExecutor mPool;
private int mCorePoolSize;
private int mMaximumPoolSize;
private long mKeepAliveTime;
private ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long keepAliveTime) {
mCorePoolSize = corePoolSize;
mMaximumPoolSize = maximumPoolSize;
mKeepAliveTime = keepAliveTime;
}
/**
* 执行任务,当线程池处于关闭,将会重新创建新的线程池
*/
public synchronized void execute(Runnable run) {
if (run == null) {
return;
}
if (mPool == null || mPool.isShutdown()) {
mPool = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
}
mPool.execute(run);
}
/**
* 取消线程池中某个还未执行的任务
*/
public synchronized void cancel(Runnable run) {
if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {
mPool.getQueue().remove(run);
}
}
/**
* 取消线程池中某个还未执行的任务
*/
public synchronized boolean contains(Runnable run) {
if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {
return mPool.getQueue().contains(run);
} else {
return false;
}
}
/**
* 立刻关闭线程池,并且正在执行的任务也将会被中断
*/
public void stop() {
if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {
mPool.shutdownNow();
}
}
/**
* 平缓关闭单任务线程池,但是会确保所有已经加入的任务都将会被执行完毕才关闭
*/
public synchronized void shutdown() {
if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {
mPool.shutdownNow();
}
}
}
调用:
通过 ThreadManager.getLongPool().excute调用
结语:本文章借鉴
https://www.jianshu.com/p/210eab345423