我们知道线程是CPU调度的最小单位。在Android中主线程是不能够做耗时操作的,子线程是不能够更新UI的。在Android中,除了Thread外,扮演线程的角色有很多,如AsyncTask,IntentService和HandlerThread等等。由于内容过多,所以将分为上下两部分,第一部分主要和大家谈谈Android中的线程,以及在Android中的常用的线程池。第二部分我们一起来了解一下AsyncTask的使用和工作原理。
1、HandlerThread
HandlerThread是Thread的子类,它是一种可以使用Handler的Thread,它的实现比较简单。我们来看看它的源码:
1 package android.os;
2
3 public class HandlerThread extends Thread {
4 int mPriority;
5 int mTid = -1;
6 Looper mLooper;
7
8 public HandlerThread(String name) {
9 super(name);
10 mPriority = Process.THREAD_PRIORITY_DEFAULT;
11 }
12
13
14 public HandlerThread(String name, int priority) {
15 super(name);
16 mPriority = priority;
17 }
18
19
20 protected void onLooperPrepared() {
21 }
22
23
24
25 @Override
26 public void run() {
27 mTid = Process.myTid();
28 Looper.prepare();
29 synchronized (this) {
30 mLooper = Looper.myLooper();
31 notifyAll();
32 }
33 Process.setThreadPriority(mPriority);
34 onLooperPrepared();
35 Looper.loop();
36 mTid = -1;
37 }
38
39
40
41 public Looper getLooper() {
42 if (!isAlive()) {
43 return null;
44 }
45
46 // If the thread has been started, wait until the looper has been created.
47 synchronized (this) {
48 while (isAlive() && mLooper == null) {
49 try {
50 wait();
51 } catch (InterruptedException e) {
52 }
53 }
54 }
55 return mLooper;
56 }
57
58
59
60 public boolean quit() {
61 Looper looper = getLooper();
62 if (looper != null) {
63 looper.quit();
64 return true;
65 }
66 return false;
67 }
68
69
70
71
72
73 public boolean quitSafely() {
74 Looper looper = getLooper();
75 if (looper != null) {
76 looper.quitSafely();
77 return true;
78 }
79 return false;
80 }
81
82
83
84
85 public int getThreadId() {
86 return mTid;
87 }
88 }
为了让大家看清楚,我们源码的一些英文注释干掉了,现在就很清晰了。整个类中,除了构造方法和对外提供几个public方法以外,就剩一个方法了run()。从它的实现来看,和普通的Thread实现没有什么区别。都是在run()方法中执行耗时操作。不过,HandlerThread内部创建了消息队列,并且run()方法是一个无限循环的方法,当我们不需要HandlerThread的时候,我们可以调用quitSafely()或者quit()方法来结束这个线程。这是比较方便的。
2、IntentService
IntentService是一种特殊的Service,它是Service的子类,并且它是一个抽象类,所以必须创建它的子类才可以使用Intent Service。Intent Service可用于执行后台的耗时任务,当任务执行完毕,它会自己结束,不需要开发着手动结束它。这里需要注意一个问题,Intentservice内置有线程,但是它还是属于Service,所以它的优先级会比线程高很多,所以不容易被系统杀死。所以比较合适去执行一些优先级比较高的任务。看看它的源码:
1 package android.app;
2
3 import android.annotation.WorkerThread;
4 import android.annotation.Nullable;
5 import android.content.Intent;
6 import android.os.Handler;
7 import android.os.HandlerThread;
8 import android.os.IBinder;
9 import android.os.Looper;
10 import android.os.Message;
11
12
13
14 public abstract class IntentService extends Service {
15 private volatile Looper mServiceLooper;
16 private volatile ServiceHandler mServiceHandler;
17 private String mName;
18 private boolean mRedelivery;
19
20
21
22 private final class ServiceHandler extends Handler {
23 public ServiceHandler(Looper looper) {
24 super(looper);
25 }
26
27
28
29 @Override
30 public void handleMessage(Message msg) {
31 onHandleIntent((Intent)msg.obj);
32 stopSelf(msg.arg1);
33 }
34 }
35
36
37
38
39 public IntentService(String name) {
40 super();
41 mName = name;
42 }
43
44
45
46
47 public void setIntentRedelivery(boolean enabled) {
48 mRedelivery = enabled;
49 }
50
51 @Override
52 public void onCreate() {
53 // TODO: It would be nice to have an option to hold a partial wakelock
54 // during processing, and to have a static startService(Context, Intent)
55 // method that would launch the service & hand off a wakelock.
56
57 super.onCreate();
58 HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
59 thread.start();
60
61 mServiceLooper = thread.getLooper();
62 mServiceHandler = new ServiceHandler(mServiceLooper);
63 }
64
65
66
67
68 @Override
69 public void onStart(@Nullable Intent intent, int startId) {
70 Message msg = mServiceHandler.obtainMessage();
71 msg.arg1 = startId;
72 msg.obj = intent;
73 mServiceHandler.sendMessage(msg);
74 }
75
76
77
78
79 @Override
80 public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
81 onStart(intent, startId);
82 return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
83 }
84
85
86
87
88 @Override
89 public void onDestroy() {
90 mServiceLooper.quit();
91 }
92
93
94
95
96 public IBinder onBind(Intent intent) {
97 return null;
98 }
99
100
101
102
103 @WorkerThread
104 protected abstract void onHandleIntent(@Nullable Intent intent);
105 }
这里就很简单了,这些方法对于经常使用Service的朋友来说,就很熟悉了。大家看onCreate()方法。没错IntentService就是封装了HandlerThread和Handler。
当我们启动IntentService是onCreate(),方法将会被调用,然后就会创建HandlerThread和ServiceHandler。而onStartCommand()方法又调用了onStart()方法,从onStart()方法可以看出IntentService 仅仅是通过ServiceHandler来发一个消息,这个消息会在HandlerThread中被处理掉。
大家看这个onStart()方法,将intent作为消息传递给onHandleIntent,这个intent通常是我们传递进来的数据。而onHandleIntent就是通过这个intent来区别具体的后台任务的。
好了,AsyncTask的使用和工作原理。我们会在下一章在说。下面我们看看线程池吧。
不知道大家有没有遇到过这种情况。我们在写项目,遇到耗时操作的时候,怎么办呢,是不是new Thread().start,那这样的话,整个项目中得new多少个Thread。这种明显是很浪费性能。毕竟线程也是好资源的嘛。那么有没有一种可以方法对线程进行复用呢?答案就是线程池。
先说一下线程池的好处:
1、重用线程池中的线程,避免因为线程的创建和销毁带来的性能开销。
2、能有效的控制线程池中的线程并发数,避免大量线程之间因为互相抢占资源而导致的阻塞现象。
3、能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。
ThreadPoolExecutor
Android中的线程池概念是来源于java中Executor,Executor是一个空的接口,真正的线程池实现ThreadPoolExecutor。
1 public ThreadPoolExecutor(int corePoolSize,
2 int maximumPoolSize,
3 long keepAliveTime,
4 TimeUnit unit,
5 BlockingQueue<Runnable> workQueue,
6 ThreadFactory threadFactory) {
7 this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
8 threadFactory, defaultHandler);
9 }
简单介绍一下ThreadPoolExcutor各个参数的含义
corePoolSize:线程池的核心线程数,默认情况下,核心线程会在线程池中一直存活,即使他们处于闲置状态。当我们把ThreadPoolExecutor中的allowCoreThreadTimeOut属性设置为true,那么闲置的核心线程在等待新任务的时候,如果时间超过keepAliveTime所设置的时间,核心线程将会被回收。
maximumPoolSize:设置最大线程池能够容纳的最大线程数,当线程池中的线程达到这个数以后,新任务将会被阻塞。
keepAliveTime:非核心线程数闲置的时间。
unit:指定keepAliveTime参数的时间单位。
workQueue:线程池中的任务队列。
threadFactory:线程工厂,为线程池提供创建新线程的功能。
线程池的分类
Android中常见的线程池有四种,FixedThreadPool、CachedThreadPool、ScheduledThreadPool、SingleThreadExecutor。
FixedThreadPool
FixedThreadPool线程池是通过Executors的new FixedThreadPool方法来创建。它的特点是该线程池中的线程数量是固定的。即使线程处于闲置的状态,它们也不会被回收,除非线程池被关闭。当所有的线程都处于活跃状态的时候,新任务就处于队列中等待线程来处理。注意,FixedThreadPool只有核心线程,没有非核心线程。
1 public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
2 return new ThreadPoolExecutor(nThreads, nThreads,
3 0L, TimeUnit.MILLISECONDS,
4 new LinkedBlockingQueue<Runnable>(),
5 threadFactory);
6 }
CachedThreadPool
CachedThreadPool线程池是通过Executors的newCachedThreadPool进行创建的。它是一种线程数目不固定的线程池,它没有核心线程,只有非核心线程,当线程池中的线程都处于活跃状态,就会创建新的线程来处理新的任务。否则就会利用闲置的线程来处理新的任务。线程池中的线程都有超时机制,这个超时机制时长是60s,超过这个时间,闲置的线程就会被回收。这种线程池适合处理大量并且耗时较少的任务。这里得说一下,CachedThreadPool的任务队列,基本都是空的。
1 public static ExecutorService newCachedThreadPool() {
2 return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
3 60L, TimeUnit.SECONDS,
4 new SynchronousQueue<Runnable>());
5 }
ScheduledThreadPool
ScheduledThreadPool线程池是通过Executors的newScheduledThreadPool进行创建的,它的核心线程是固定的,但是非核心线程数是不固定的,并且当非核心线程一处于空闲状态,就立即被回收。这种线程适合执行定时任务和具有固定周期的重复任务。
1 public static ScheduledExecutorService newScheduledThreadPool(
2 int corePoolSize, ThreadFactory threadFactory) {
3 return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
4 }
5
6
7 public ScheduledThreadPoolExecutor(int corePoolSize,
8 ThreadFactory threadFactory) {
9 super(corePoolSize, Integer.MAX_VALUE,
10 DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
11 new DelayedWorkQueue(), threadFactory);
12 }
SingleThreadExecutor
SingleThreadExecutor线程池是通过Executors的newSingleThreadExecutor方法来创建的,这类线程池中只有一个核心线程,也没有非核心线程,这就确保了所有任务能够在同一个线程并且按照顺序来执行,这样就不需要考虑线程同步的问题。
1 public static ExecutorService newSingleThreadExecutor() {
2
3 return new FinalizableDelegatedExecutorService
4
5 (new ThreadPoolExecutor(1, 1,
6
7 0L, TimeUnit.MILLISECONDS,
8
9 new LinkedBlockingQueue<Runnable>()));
10
11 }
好了,写了这么多,真特么累,下部分就和大家分享一下AsyncTask的 工作原理。
来源:https://www.cnblogs.com/huangjialin/p/8546513.html