1. 线程形态
1.1 AsyncTask
它是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递到主线程并在主线程更新UI。从实现上来说,它封装了Thread和Handler,通过AsyncTask可以更加方便地执行后台任务以及在主线程中访问UI。但是不适合进行特别耗时的后台任务,对于特别耗时的后台任务来说,建议使用线程池。
AsyncTask是一个抽象的泛型类,它提供了Params、Progress和Result三个泛型参数,如果需要传递具体的参数,那么这三个泛型参数可以用Void代替。
AsyncTask提供了4个核心方法:
1)onPreExecute():在调用execute的线程执行,在异步任务开始之前,此方法会被调用,用于做一些准备工作;
2)doInBackground(Params... params):在线程池中执行,返回的结果会给onPostExecute作为参数。
3)onProgressUpdate(Progress... values):在主线程中执行,publishProgress方法被调用时会进入这个方法。
4)onPostExecute(Result result):在主线程中执行,其中result参数是后台任务的返回值。
下面贴上一段示例代码:
private void test() {
new MainTask().execute("hello world");
}
private class MainTask extends AsyncTask<String, Integer, String> {
@Override
protected String doInBackground(String... strings) {
Log.i(TAG, "doInBackground: " + strings[0]);
for (int i=0; i<3;i++) {
publishProgress(i);
}
return strings[0];
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Log.i(TAG, "onProgressUpdate: " + values[0]);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.i(TAG, "onPostExecute: " + s);
}
}
1.2 HandlerThread
HandlerThread继承了Thread,它是一种可以使用Handler的Thread,就是在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环。
run方法代码如下:
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
1.3 IntentService
IntentService是一种特殊的Service,它可以在后台执行耗时任务,当任务执行结束会自动停止,同时由于IntentService是服务的原因,所以它的优先级比单纯的线程要高很多。它封装了HandlerThread和Handler,这点从它的onCreate()方法中看出来,如下所示:
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
每次启动IntentService时,会将传进来的intent发送给Handler处理,
/**
* You should not override this method for your IntentService. Instead,
* override {@link #onHandleIntent}, which the system calls when the IntentService
* receives a start request.
* @see android.app.Service#onStartCommand
*/
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
2. Android中的线程池
采用线程池的优点:
1)重用线程池中的线程,避免因为线程的创建和销毁所带来的性能下降;
2)能有效控制线程池的最大并发数,避免大量的线程之间因为互相抢占资源而导致的阻塞现象;
3)能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。
Android中的线程池概念来源于Java中的Executor,Executor是一个接口,真正的线程池实现为ThreadPoolExecutor。Android的线程池主要分为4类,可以通过Executors所提供的工厂方法来得到。
/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters and default thread factory and rejected execution handler.
* It may be more convenient to use one of the {@link Executors} factory
* methods instead of this general purpose constructor.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
2.1 FixedThreadPool
它是一种线程数量固定的线程池,当线程处于空闲状态时,它们并不会被回收,除非线程池被关闭了。
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
* {@code nThreads} threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* prior to shutdown, a new one will take its place if needed to
* execute subsequent tasks. The threads in the pool will exist
* until it is explicitly {@link ExecutorService#shutdown shutdown}.
*
* @param nThreads the number of threads in the pool
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code nThreads <= 0}
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
2.2 CachedThreadPool
它是一种线程数量不固定的线程池,它只有非核心线程,并且最大线程数为Integer.MAX_VALUE。
/**
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
* Calls to {@code execute} will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
* the cache. Thus, a pool that remains idle for long enough will
* not consume any resources. Note that pools with similar
* properties but different details (for example, timeout parameters)
* may be created using {@link ThreadPoolExecutor} constructors.
*
* @return the newly created thread pool
*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
2.3 ScheduledThreadPool
它的核心线程数量是固定的,而非核心线程数是没有限制的,并且当非核心线程闲置时会被立即回收,主要用于执行定时任务和具有固定周期的重复任务。
/**
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
* even if they are idle
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
/**
* Creates a new {@code ScheduledThreadPoolExecutor} with the
* given core pool size.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
2.4 SingleThreadPool
它内部只有一个核心线程,它确保所有的任务都在同一个线程中按顺序执行。它的意义在于统一所有的外界任务到一个线程中,它使得在这些任务之间不需要处理线程同步的问题。
/**
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue, and uses the provided ThreadFactory to
* create a new thread when needed. Unlike the otherwise
* equivalent {@code newFixedThreadPool(1, threadFactory)} the
* returned executor is guaranteed not to be reconfigurable to use
* additional threads.
*
* @param threadFactory the factory to use when creating new
* threads
*
* @return the newly created single-threaded Executor
* @throws NullPointerException if threadFactory is null
*/
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
网友评论