相关线程知识先扩充一下:
主线程和子线程
主线程(也叫UI线程):在java中默认情况下一个进程只有一个线程,这个线程就是主线程。其主要作用是处理和界面交互相关的逻辑,主线程不能做太多耗时的操作,否则会产生界面卡顿的感觉。为保持较快的响应速度,子线程就出场了。
子线程:也叫工作线程,除了主线程之外的都是子线程。
基本用途:主线程是运行四大组件及处理它们和用户的交互,子线程处理耗时的任务,如网络请求、I/O操作等。
Android中的线程表现形式:
Thread、AsyncTask、HanderThread、IntentService.
简单介绍一下后三者的注意事项
1.AysncTask: 可理解为轻量级的线程池,异步任务类,其封装了Thread和Handler,通过AysncTask可以很方便的执行后台任务及在主线程中访问UI.
缺点:不适合进行特别耗时的后台任务,对于特别耗时的任务最好用池线程池替换。
2.HandlerThread: 继承自Thread,它是一种可以 使用Handler和Thread.实现也很简单,在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环。
3.IntentService: 继承自Service,是一个抽象类,所以必须创建他的子类才能使用IntentSerivce,可用于执行后台耗时任务,当任务完成后会自动停止,该优先级高于其他单纯的线程,不容易补系统杀死。 IntentSerivce 封装了Handler和HandlerThread.
线程池的好处:
1.Android中像访问内存卡,联网等耗时较长的任务时,需要在异步线程中进行,所以需要新开线程进行。但创建或者销毁线程伴随着系统的开销,频繁的创建和销毁线程,会较大的影响系统的性能。使用线程池,可用已有的闲置线程来执行新任务。
2.我们知道线程能共享系统资源,如果同时执行的线程过多,就有可能导致系统资源不足而产生阻塞的情况,运用线程池能有效的控制线程最大并发数(maximumPoolSize),避免以上的问题。
3.线程池能够对线程进行有效的管理,比如延时执行,定时定周期循环执行等。
Android中的线程池来源于java,主要是通过Executor 来派生特定类型的线程池,不同类型的线程池有不同的意义。Executor是一个接口,真正地实现为ThreadPoolExecutor,他提供了一系列的参数来配置线程池。不同参数意味着不同的线程池。
最后该介绍一下主角线程池了。它分为四种:
FixedThreadPool
特点:
①可控制线程最大并发数(线程数固定)
②超出的线程会在队列中等待
使用优势:能够更快的响应外界的请求。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L,TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
CachedThreadPool
缓存线程池的特点:
① 线程数无限制
② 没有核心线程,都是非核心线程
优势:比较适合用来执行大量的但是耗时较少的任务。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
ScheduledThreadPool
使用场景:用于执行定时任务和具有固定周期的重复任务。
SingleTreadExecutor
使用场景:按顺序执行,不需要处理同步的问题。
据此 四种线程池简单介绍完成,下面介绍下如何封装使用线程池。
/**
* 线程池封装
*
* @author jun.yang
* created at 2018/2/26 10:21
*/
public class ThreadPoolManager {
private static ThreadPoolManager mInstance;
public static ThreadPoolManager getInstance() {
if (mInstance == null) {
synchronized (ThreadPoolManager.class) {
if (mInstance == null) {
mInstance = new ThreadPoolManager();
}
}
}
return mInstance;
}
/**
* 核心线程池的数量,同时能够执行的线程数量
*/
private int corePoolSize;
/**
* 最大线程池数量,表示当缓冲队列满的时候能继续容纳的等待任务的数量
*/
private int maximumPoolSize;
/**
* 存活时间
*/
private long keepAliveTime = 1;
private TimeUnit unit = TimeUnit.HOURS;
private ThreadPoolExecutor executor;
private ThreadPoolManager() {
/**
* 给corePoolSize赋值:当前设备可用处理器核心数*2 + 1,能够让cpu的效率得到最大程度执行(有研究论证的)
*/
corePoolSize = Runtime.getRuntime().availableProcessors() * 2 + 1;
//虽然maximumPoolSize用不到,但是需要赋值,否则报错
maximumPoolSize = corePoolSize;
executor = new ThreadPoolExecutor(
//当某个核心任务执行完毕,会依次从缓冲队列中取出等待任务
corePoolSize,
//5,先corePoolSize,然后new LinkedBlockingQueue<Runnable>(),然后maximumPoolSize,但是它的数量是包含了corePoolSize的
maximumPoolSize,
//表示的是maximumPoolSize当中等待任务的存活时间
keepAliveTime,
unit,
//缓冲队列,用于存放等待任务,Linked的先进先出
new LinkedBlockingQueue<Runnable>(),
//创建线程的工厂
// Executors.defaultThreadFactory(),
new DefaultThreadFactory(Thread.NORM_PRIORITY, "tiaoba-pool-"),
//用来对超出maximumPoolSize的任务的处理策略
new ThreadPoolExecutor.AbortPolicy()
);
}
/**
* 执行任务
*
* @param runnable
*/
public void execute(Runnable runnable) {
if (executor == null) {
//线程池执行者。
//参1:核心线程数;参2:最大线程数;参3:线程休眠时间;参4:时间单位;参5:线程队列;参6:生产线程的工厂;参7:线程异常处理策略
executor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
// Executors.defaultThreadFactory(),
new DefaultThreadFactory(Thread.NORM_PRIORITY, "tiaoba-pool-"),
new ThreadPoolExecutor.AbortPolicy());
}
if (runnable != null) {
executor.execute(runnable);
}
}
/**
* 移除任务
*/
public void remove(Runnable runnable) {
if (runnable != null) {
executor.remove(runnable);
}
}
/**
* 创建线程的工厂,设置线程的优先级,group,以及命名
*/
private static class DefaultThreadFactory implements ThreadFactory {
/**
* 线程池的计数
*/
private static final AtomicInteger poolNumber = new AtomicInteger(1);
/**
* 线程的计数
*/
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final String namePrefix;
private final int threadPriority;
DefaultThreadFactory(int threadPriority, String threadNamePrefix) {
this.threadPriority = threadPriority;
this.group = Thread.currentThread().getThreadGroup();
namePrefix = threadNamePrefix + poolNumber.getAndIncrement() + "-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
if (t.isDaemon()) {
t.setDaemon(false);
}
t.setPriority(threadPriority);
return t;
}
}
}
调用方法:
ThreadPoolManager.getInstance().execute(command));
Runnable command = new Runnable(){
@Override
public void run(){
SystemClock.sleep(2000)
}
}