线程池的作用:
对多个线程进行统一地管理,避免资源竞争中出现的问题。对线程进行复用,线程在执行完任务后不会立刻销毁,而会等待另外的任务,这样就不会频繁地创建、销毁线程和调用GC。JAVA提供了一套完整的ExecutorService线程池创建的api,可创建多种功能不一的线程池,使用起来很方便。
创建线程池(基类ThreadPoolExecutor)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
...
}
corepoolSize:核心线程数
maximumPoolSize: 线程池最大线程数量,非核心线程数=maxinumPoolSize - corepoolSize;
keepAliveTime:超时时长,作用于非核心线程(allowCoreThreadTimeOut被设置为true时也会同时作用于核心线程),闲置超时便被回收
unit:枚举类型,设置keepAliveTime的单位,有TimeUnit.MILLISECONDS(ms)、TimeUnit. SECONDS(s)等
workQueue:缓冲任务队列,线程池的execute方法会将Runnable对象存储起来
threadFactory::线程工厂,可用于设置线程名字等等,一般无须设置该参数
案例
//创建基本线程池
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,5,1,TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(100));
/**
* 基本线程池使用
*/
mThreadPoolExecute.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for(int i = 0;i<30;i++){
final int finali = i;
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
Log.d("Thread", "run: "+finali);
Log.d("当前线程:",Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
threadPoolExecutor.execute(runnable);
}
}
});
(1)当currentSize<corePoolSize时,没什么好说的,直接启动一个核心线程并执行任务。
(2)当currentSize>=corePoolSize、并且workQueue未满时,添加进来的任务会被安排到workQueue中等待执行。
(3)当workQueue已满,但是currentSize<maximumPoolSize时,会立即开启一个非核心线程来执行任务。
(4)当currentSize>=corePoolSize、workQueue已满、并且currentSize>maximumPoolSize时,调用handler默认抛出RejectExecutionExpection异常。
其他基本线程
Android中最常见的四类具有不同特性的线程池分别为FixThreadPool、CachedThreadPool、ScheduleThreadPool以及SingleThreadExecutor。
1:FixedThreadPool (可重用固定线程数)
1 /*
2 *@FixThreadPool介绍
3 *@author SEU_Calvin
4 * @date 2016/09/03
5 */
6 public static ExecutorService newFixThreadPool(int nThreads){
7 return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
8 }
9 //使用
10 Executors.newFixThreadPool(5).execute(r);
FixThreadPool只有核心线程,并且数量固定的,也不会被回收,所有线程都活动时,因为队列没有限制大小,新任务会等待执行。
3:CachedThreadPool (按需创建)
1 /*
2 *@CachedThreadPool介绍
3 *@author SEU_Calvin
4 * @date 2016/09/03
5 */
6 public static ExecutorService newCachedThreadPool(int nThreads){
7 return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit. SECONDS, new SynchronousQueue<Runnable>());
8 }
9 //使用
10 Executors.newCachedThreadPool().execute(r);
(1)CachedThreadPool只有非核心线程,最大线程数非常大,所有线程都活动时,会为新任务创建新线程,否则利用空闲线程(60s空闲时间,过了就会被回收,所以线程池中有0个线程的可能)处理任务。
(2)任务队列SynchronousQueue相当于一个空集合,导致任何任务都会被立即执行。
(3)比较适合执行大量的耗时较少的任务。
3:SingleThreadPool(单个核线的fixed)
/*
*@SingleThreadPool介绍
*@author SEU_Calvin
* @date 2016/09/03
*/
public static ExecutorService newSingleThreadPool (int nThreads){
return new FinalizableDelegatedExecutorService ( new ThreadPoolExecutor (1, 1, 0, TimeUnit. MILLISECONDS, new LinkedBlockingQueue<Runnable>()) );
}
//使用
Executors.newSingleThreadPool ().execute(r);
由于只有一个核心线程,当被占用时,其他的任务需要进入队列等待。
4:ScheduledThreadPool(定时延时执行)
1 /*
2 *@ScheduledThreadPool介绍
3 *@author SEU_Calvin
4 * @date 2016/09/03
5 */
6 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize){
7 return new ScheduledThreadPoolExecutor(corePoolSize);
8 }
9 public ScheduledThreadPoolExecutor(int corePoolSize){
10 super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedQueue ());
11 }
12 //使用,延迟1秒执行,每隔2秒执行一次Runnable r
13 Executors. newScheduledThreadPool (5).scheduleAtFixedRate(r, 1000, 2000, TimeUnit.MILLISECONDS);
核心线程数固定,非核心线程(闲着没活干会被立即回收)数没有限制。
各个线程池总结及适用场景
newCachedThreadPool:
适用:执行很多短期异步的小程序或者负载较轻的服务器
newFixedThreadPool:
适用:执行长期的任务,性能好很多
newSingleThreadExecutor:
适用:一个任务一个任务执行的场景
NewScheduledThreadPool:
适用:周期性执行任务的场景
线程池其它方法:
1.shutDown() 关闭线程池,不影响已经提交的任务
2.shutDownNow() 关闭线程池,并尝试去终止正在执行的线程
3.allowCoreThreadTimeOut(boolean value) 允许核心线程闲置超时时被回收
4.submit 一般情况下我们使用execute来提交任务,但是有时候可能也会用到submit,使用submit的好处是submit有返回值。
5.beforeExecute() - 任务执行前执行的方法
6.afterExecute() -任务执行结束后执行的方法
7.terminated() -线程池关闭后执行的方法
https://www.jianshu.com/p/7b2da1d94b42
、