我们知道线程是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