Android的线程和线程池

Android沿用了Java的线程模型,线程分为主线程和子线程,主线程主要负责处理和界面相关的事情,而子线程则主要用于执行耗时操作,其中主线程也叫UI线程。

除了Thread外,Android还提供AsyncTask、IntentService和HandlerThread这些特殊的线程,尽管他们的表现形式有别于传统的线程,但是它们本质仍然是传统的线程。AsyncTask底层用到了线程池,IntentService和HandlerThread底层则直接用到了线程。

● AsyncTask——封装了线程池和Handler,它主要是为了方便开发者在子线程中更新UI;

● IntentService——是一种服务,内部采用HandlerThread来执行任务,系统封装使其更方便执行后台任务;

● HandlerThread——一种具有消息循环的线程,在它内部可以使用Handler。

AsyncTask

   AsyncTask是一种轻量级的异步任务类,

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;
}

普通Thread一般执行耗时操作,而HanderThread不同之处在于,内部创建了消息队列,外界可以通过handler的消息方式来通知HandlerThread执行一个具体的任务。具体的使用场景是就是IntentService。

由于HandlerThread的run是一个无限循环,因此当明确不需要HandlerThread时,可以通过它的quit或者quitSafely方法来终止制线程的执行。

IntentService

  IntentService是一种特殊的Service,它继承了Service并且它是一个抽象类,同时IntentService是服务的原因,这导致它的优先级比单纯的线程要高得多,所以它比较适合执行一些高优先级的后台任务,不容易被系统杀死,IntentService可用于执行后台耗时的任务,当任务执行后它会自动停止。

  在实现上,IntentService封装了HandlerThread和Handler,从它的onCreate方法中可以看出:

public void onCreate() {
    super.onCreate();
    HandlerThread thread = new HandlerThread("IntentService["+ mName +"]");
    thread.start();

    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);

}

这样mServiceHandler发送的消息最终都会在HandlerThread中执行,IntentService在onStartCommand方法中处理每个后台任务的Intent,onStartCommand调用了onStart方法,看下onStart的具体实现

public void onStart(Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

ServiceHandler的实现如下:

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);
    }
}

IntentService的onHandleIntent方法是一个抽象方法,作用是从Intent参数中区分具体的任务并执行这些任务。

如果目前只存在一个后台任务,那么onHandleIntent执行完这个任务后,stopSelf(int startId)就会直接停止服务,如果目前存在多个后台任务,那么onHandleIntent执行完最后一个任务stopSelf才停止服务,stopSelf(int startId)在尝试停止服务之前会判断最近启动服务的次数是否和startId相等,如果相等就立刻停止服务。

IntentService使用示例如下:

public class LocalIntentService extends IntentService {

    private static final String TAG = LocalIntentService.class.getSimpleName();

    public LocalIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        String action = intent.getStringExtra("task_action");
        Log.d(TAG, "receive task: " + action);
        SystemClock.sleep(3000);
        if ("com.gomez.action.task1".equals(action)) {
            Log.d(TAG, "handle task: " + action);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: service destroyed");

    }
}

通过示例可以发现IntentService是按外界顺序执行后台任务的,因为Handler中的Looper是顺序处理消息的。

线程池的分类

常用的4类线程池分别为FixThreadPool、CachedThreadPool、ScheduleThreadPool和SingleThreadExecutor。

FixThreadPool

    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>());
    }

①线程数量可以任意大

②没有核心线程,闲置线程60秒会被回收

③任务队列无法插入任务

ScheduleThreadPool


    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
              new DelayedWorkQueue());
    }

①核心线程是固定的,非核心线程数没有限制

②非核心线程闲置会被马上回收

③任务队列大小没有限制

SingleThreadExecutor

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

①只有1个核心线程,没有非核心线程

②线程不会被回收

具体使用示例如下:

        Runnable task = new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(2000);
            }
        };
        ExecutorService fixThreadPool = Executors.newFixedThreadPool(4);
        fixThreadPool.execute(task);
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        cachedThreadPool.execute(task);
        ScheduledExecutorService scheduleThreadPool = Executors.newScheduledThreadPool(4);
        //2s后执行task
        scheduleThreadPool.schedule(task, 2000, TimeUnit.MILLISECONDS);
        //延时10ms后执行,每隔1s执行一次task
        scheduleThreadPool.scheduleAtFixedRate(task,10, 1000, TimeUnit.MILLISECONDS);
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        singleThreadExecutor.execute(task);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章