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

 

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