参考资料
目录
- 1)主线程和子线程
- 2)线程形态
- 2.1)AsyncTask
- 2.2)HandlerThread
- 2.3)IntentService
- 3)线程池
- 3.1)ThreadPoolExecutor
- 3.2)线程池的分类
1)主线程和子线程
2)线程形态
2.1)AsyncTask
封装了线程池和Handler,主要方便在子线程中更新UI。
//Params 参数类型
//Progress 后台任务执行进度的类型
//Result 后台任务返回结果的类型
public abstract class AsyncTask<Params,Progress,Result>
//四个方法
//在主线程中执行,异步任务执行前,此方法被调用
onPreExecute()
//线程池中执行
doInBackground(Params...params){
//更新进度,会调用onProgressUpdate()
publicProgress(values);
}
//异步任务取消时被调用
onCancelled()
//主线程中执行,执行进度发生改变调用
onProgressUpdate(Progress...values)
//主线程中执行,异步任务结束后会调用
onPostExecute(Result result)
注意:
- AsyncTask的实例必须在UI thread中创建;
- execute方法必须在UI thread中调用;
- 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
- 一个AsyncTask只能被执行一次,即execute()只能被调用一次,否则多次调用时将会出现异常;
//AsyncTask从Android3.0开始,默认情况下是串行执行的。为了让其在Android3.0及以上版本并行执行,可以采用
new mAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
AsyncTask中有两个线程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一个Handler(InternalHandler),
SerialExecutor用于任务排队,而THREAD_POOL_EXECUTOR用于执行任务,InternalHandler则是将执行环境从线程池切换到主线程。
2.2)HandlerThread
HandlerThread继承了Thread,是一种可以使用Handler的Thread,其实它就是在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环。它有个具体使用场景,就是IntentService。
示例1:
// Step 1: 创建并启动HandlerThread线程,内部包含Looper
HandlerThread handlerThread = new HandlerThread("tgf");
handlerThread.start();
// Step 2: 创建Handler
Handler handler = new Handler(handlerThread.getLooper());
// Step 3: 发送消息
handler.post(new Runnable() {
@Override
public void run() {
System.out.println("thread id="+Thread.currentThread().getId());
}
});
示例2:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
// Step 1: 创建Handler
mHandler = new Handler() {
public void handleMessage(Message msg) {
//TODO 处理即将发送过来的消息
}
};
Looper.loop();
}
}
// Step 2: 创建并启动LooperThread线程,内部包含Looper
LooperThread looperThread = new LooperThread("tgf");
looperThread.start();
// Step 3: 发送消息
looperThread.mHandler.sendEmptyMessage(10);
2.3)IntentService
https://mp.weixin.qq.com/s?__biz=MzI0MjE3OTYwMg==&mid=401611665&idx=1&sn=9b6b1f2924d4adfe4e89a322ab53df9c&scene=21#wechat_redirect
IntentService是一个服务,内部采用HandlerThread来执行任务,HandlerThread是一个工作线程(子线程),其Handler的handleMessage会回调onHandleIntent并stopSelf,执行完毕自动退出。很像是一个后台线程,但却是一个服务,所以不容易被系统杀死。
- 多次startService(Intent intent)会串行执行onHandleIntent()
- 只能startService启动,源码中onBind => return null;
@override
protected void onHandleIntent(Intent intent)
3)线程池
线程是操作系统调度的最小单元,它的创建和销毁都有相应的开销,当系统中存在大量线程时,系统会通过时间片轮转的方式调度。频繁的创建和销毁线程并不高效。正确的方式是采用线程池,一个线程池中缓存一定数量线程,减小开销。
线程池优点 |
---|
避免重复创建销毁的开销 |
控制最大并发,避免大量线程争抢资源 |
有效的管理,如可以定时或指定间隔循环执行等 |
Java的线程池来源于Executor接口,真正实现为ThreadPoolExecutor
3.1)ThreadPoolExecutor
//corePoolSize 核心线程数,默认核心线程会在线程池内一直存活,除非设定allowCoreThreadTimeOut=true。
//maximumPoolSize 最大线程数,活动线程达到此峰值,后续任务将被阻塞
//keepAliveTime 非核心线程超时时间,超过则被回收
//unit keepAliveTime的时间单位,枚举TimeUnit.MILLSECONDS(毫秒), TimeUnit.SECONDS(秒)等。
//workQueue 任务队列,提交的任务runnable对象被存储在这
//threadFactory 线程工厂,为线程池创建新线程。
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory
)
ThreadPoolExecutor执行任务的规则 |
---|
当前线程数量<核心线程数,启动一个核心线程执行任务 |
当前线程数量>=核心线程数,将任务插入任务队列排队 |
任务队列满了,当前线程数<最大线程数,启动非核心线程执行任务 |
任务队列满了,当前线程数>=最大线程数,拒绝此任务 |
3.2)线程池的分类
分类 | 说明 |
---|---|
FixedThreadPool | 只有数量固定核心线程,无超时。所以能快速响应 |
CachedThreadPool | 只有非核心线程,最大数量Integer.MAX_VALUE,空闲60秒后回收,适合大数量但耗时少任务 |
ScheduledThreadPool | 核心线程数量固定,非核心线程数无限制,非核心闲置会立即回收,适合定时任务或固定周期重复任务 |
SingleThreadPool | 只有一个核心线程,适合处理线程同步 |
- FixedThreadPool
//调用
ExecutorService a = Executor.newFixedThreadPool(4);
a.execute(runnable);
//源码
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(
nThreads,
nThreads,
0L,
TimeUnit.MILLSECONDS,
new LinkedBlockingQueue<Runnable>()
);
}
*CachedThreadPool
ExecutorService a = Executor.newCachedThreadPool();
a.execute(runnable);
public static ExecutorService newCachedThreadPool(){
return new ThreadExecutor(
0,
Integer.MAX_VALUE,
60L,
TimeUnit.SECONDS,
new SynchronousQueue<Runnable>()
);
}
- ScheduledThreadPool
ScheduledExecutorService a = Executor.newScheduledThreadPool(4);
//2000ms后执行runnable
a.schedule(runnable,2000,TimeUnit.MILLSECONDS);
//延迟10ms后,每隔1000ms执行一次runnable
a.scheduleAtFixedRate(runnable,10,1000,TimeUnit.MILLSECONDS);
public static ScheduledExecutor newScheduledThreadPool(int corePoolSize){
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize){
super(corePoolSize,Integer.MAX_VALUE,0,NANOSECONDS,new DelayedWorkQueue());
}
- SingleThreadPool
ExecutorService a = Executor.newSingleThreadExecutor();
a.execute(runnable);
public static ExecutorService newSingleThreadExecutor(){
return new FinalizableDelegatedExecutorService(
new ThreadPoolExecutor(
1,1,0L,TimeUnit.MILLSECONDS,
new LinkedBlockingQueue<Runnable>()
)
);
}
网友评论