Android-线程池
2020-09-22 本文已影响0人
有腹肌的豌豆Z
- 线程池就是创建若干个可执行的线程放入一个池(容器)中,有任务需要处理时,会提交到线程池中的任务队列,处理完之后线程并不会立即被销毁,而是仍然在线程池中等待下一个任务。
为什么要使用线程池
- 减少线程频繁创建、销毁的开销;
- 好控制并发量,降低OOM的可能,至于原因文中会说;
- 提高程序的响应速度,因为可以省去部分创建的过程;
图解
Executor接口
public interface Executor {
/**
* 就一个方法,用来执行线程任务的,类似于Thread的start()方法
*/
void execute(Runnable command);
}
- 由于Executor是一个接口,所以execute是由具体的实现类来完成的,调用这个方法,可能会出现如下情况:
1.创建一个新线程并立即启动;
2.复用线程池中空闲的线程来执行任务;
3.进入一个阻塞队列中排队;
4.抛出异常/拒绝接收该任务,这个要看具体的拒绝策略,默认抛出异常。
ExecutorService接口
- 继承自Executor接口,我们常用的很多方法就是在这个接口中定义的。主要涉及到:提交任务、关闭线程、获取结果。
public interface ExecutorService extends Executor {
/**
* 关闭线程池,新提交的任务会被拒绝,但是已经提交的任务会继续执行
*/
void shutdown();
/**
* 关闭线程池,新提交的任务会被拒绝,并且尝试关闭正在执行的任务
*/
List<Runnable> shutdownNow();
/**
* 线程池是否已关闭
*/
boolean isShutdown();
/**
* 如果调用了shutdown或者shutdownNow之后,所有的任务都结束了,那么返回true,否则返回false
*/
boolean isTerminated();
/**
* 当调用shutdown 或 shutdownNow之后,再调用这个方法,会
*等待所有的任务执行完成,直到超时(超过timeout)或者说当前的线程被中断了
*/
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
/**
* 提交一个Runnable 任务
*/
Future<?> submit(Runnable task);
/**
* 执行所有任务,返回 Future 类型的一个 list
*/
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
}
AbstractExecutorService
- 抽象类,实现了ExecutorService接口。主要封装了通过submit方式提交任务的一些操作。
- 注意: 不需要获取结果,可以用 execute 方法;需要获取结果(FutureTask)用 submit 方法。
Executors
- 这是大多数人最常用的一个类,实质上就是一个工具类。可以快速的构建一个线程池对象,常见的操作有如下:
/**
* 创建一个固定大小的线程池,而且全是核心线程,
* 会一直存活,除非特别设置了核心线程的超时时间
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
/**
* 创建了一个没有大小限制的线程池,全是非核心线程;如果线程
* 空闲的时间超过60s就会被移除
*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
/**
* 这个线程池只有1个唯一的核心线程
*/
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
/**
* 创建一个定长的线程池,可以执行周期性的任务
*/
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
- 可以看出这几种方式最后都是通过ThreadPoolExecutor来实现的,所以下面就来研究一下今天的主角ThreadPoolExecutor,等理解了这个类,也就可以掌握线程池等工作原理,甚至可以根据自己的策略来自定义线程池。