分析Android中線程和線程池
前言
由于內(nèi)容過(guò)多,所以將分為上下兩部分,第一部分主要和大家談?wù)凙ndroid中的線程,以及在Android中的常用的線程池。第二部分我們一起來(lái)了解一下AsyncTask的使用和工作原理。
HandlerThread
HandlerThread是Thread的子類,它是一種可以使用Handler的Thread,它的實(shí)現(xiàn)比較簡(jiǎn)單。我們來(lái)看看它的源碼:
package android.os;
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
public int getThreadId() {
return mTid;
}
}
為了讓大家看清楚,我們?cè)创a的一些英文注釋干掉了,現(xiàn)在就很清晰了。整個(gè)類中,除了構(gòu)造方法和對(duì)外提供幾個(gè)public方法以外,就剩一個(gè)方法了run()。從它的實(shí)現(xiàn)來(lái)看,和普通的Thread實(shí)現(xiàn)沒(méi)有什么區(qū)別。都是在run()方法中執(zhí)行耗時(shí)操作。不過(guò),HandlerThread內(nèi)部創(chuàng)建了消息隊(duì)列,并且run()方法是一個(gè)無(wú)限循環(huán)的方法,當(dāng)我們不需要HandlerThread的時(shí)候,我們可以調(diào)用quitSafely()或者quit()方法來(lái)結(jié)束這個(gè)線程。這是比較方便的。
IntentService
IntentService是一種特殊的Service,它是Service的子類,并且它是一個(gè)抽象類,所以必須創(chuàng)建它的子類才可以使用Intent Service。Intent Service可用于執(zhí)行后臺(tái)的耗時(shí)任務(wù),當(dāng)任務(wù)執(zhí)行完畢,它會(huì)自己結(jié)束,不需要開(kāi)發(fā)著手動(dòng)結(jié)束它。這里需要注意一個(gè)問(wèn)題,Intentservice內(nèi)置有線程,但是它還是屬于Service,所以它的優(yōu)先級(jí)會(huì)比線程高很多,所以不容易被系統(tǒng)殺死。所以比較合適去執(zhí)行一些優(yōu)先級(jí)比較高的任務(wù)??纯此脑创a:
package android.app;
import android.annotation.WorkerThread;
import android.annotation.Nullable;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
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);
}
}
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@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);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@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 onDestroy() {
mServiceLooper.quit();
}
public IBinder onBind(Intent intent) {
return null;
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
這里就很簡(jiǎn)單了,這些方法對(duì)于經(jīng)常使用Service的朋友來(lái)說(shuō),就很熟悉了。大家看onCreate()方法。沒(méi)錯(cuò)IntentService就是封裝了HandlerThread和Handler。
當(dāng)我們啟動(dòng)IntentService是onCreate(),方法將會(huì)被調(diào)用,然后就會(huì)創(chuàng)建HandlerThread和ServiceHandler。而onStartCommand()方法又調(diào)用了onStart()方法,從onStart()方法可以看出IntentService 僅僅是通過(guò)ServiceHandler來(lái)發(fā)一個(gè)消息,這個(gè)消息會(huì)在HandlerThread中被處理掉。
大家看這個(gè)onStart()方法,將intent作為消息傳遞給onHandleIntent,這個(gè)intent通常是我們傳遞進(jìn)來(lái)的數(shù)據(jù)。而onHandleIntent就是通過(guò)這個(gè)intent來(lái)區(qū)別具體的后臺(tái)任務(wù)的。
好了,AsyncTask的使用和工作原理。我們會(huì)在下一章在說(shuō)。下面我們看看線程池吧。
不知道大家有沒(méi)有遇到過(guò)這種情況。我們?cè)趯?xiě)項(xiàng)目,遇到耗時(shí)操作的時(shí)候,怎么辦呢,是不是new Thread().start,那這樣的話,整個(gè)項(xiàng)目中得new多少個(gè)Thread。這種明顯是很浪費(fèi)性能。畢竟線程也是好資源的嘛。那么有沒(méi)有一種可以方法對(duì)線程進(jìn)行復(fù)用呢?答案就是線程池。
線程池的好處
1、重用線程池中的線程,避免因?yàn)榫€程的創(chuàng)建和銷毀帶來(lái)的性能開(kāi)銷。
2、能有效的控制線程池中的線程并發(fā)數(shù),避免大量線程之間因?yàn)榛ハ鄵屨假Y源而導(dǎo)致的阻塞現(xiàn)象。
3、能夠?qū)€程進(jìn)行簡(jiǎn)單的管理,并提供定時(shí)執(zhí)行以及指定間隔循環(huán)執(zhí)行等功能。
ThreadPoolExecutor
Android中的線程池概念是來(lái)源于java中Executor,Executor是一個(gè)空的接口,真正的線程池實(shí)現(xiàn)ThreadPoolExecutor。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
簡(jiǎn)單介紹一下ThreadPoolExcutor各個(gè)參數(shù)的含義
corePoolSize:線程池的核心線程數(shù),默認(rèn)情況下,核心線程會(huì)在線程池中一直存活,即使他們處于閑置狀態(tài)。當(dāng)我們把ThreadPoolExecutor中的allowCoreThreadTimeOut屬性設(shè)置為true,那么閑置的核心線程在等待新任務(wù)的時(shí)候,如果時(shí)間超過(guò)keepAliveTime所設(shè)置的時(shí)間,核心線程將會(huì)被回收。
maximumPoolSize:設(shè)置最大線程池能夠容納的最大線程數(shù),當(dāng)線程池中的線程達(dá)到這個(gè)數(shù)以后,新任務(wù)將會(huì)被阻塞。
keepAliveTime:非核心線程數(shù)閑置的時(shí)間。
unit:指定keepAliveTime參數(shù)的時(shí)間單位。
workQueue:線程池中的任務(wù)隊(duì)列。
threadFactory:線程工廠,為線程池提供創(chuàng)建新線程的功能。
線程池的分類
Android中常見(jiàn)的線程池有四種,F(xiàn)ixedThreadPool、CachedThreadPool、ScheduledThreadPool、SingleThreadExecutor。
FixedThreadPool
FixedThreadPool線程池是通過(guò)Executors的new FixedThreadPool方法來(lái)創(chuàng)建。它的特點(diǎn)是該線程池中的線程數(shù)量是固定的。即使線程處于閑置的狀態(tài),它們也不會(huì)被回收,除非線程池被關(guān)閉。當(dāng)所有的線程都處于活躍狀態(tài)的時(shí)候,新任務(wù)就處于隊(duì)列中等待線程來(lái)處理。注意,F(xiàn)ixedThreadPool只有核心線程,沒(méi)有非核心線程。
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
CachedThreadPool
CachedThreadPool線程池是通過(guò)Executors的newCachedThreadPool進(jìn)行創(chuàng)建的。它是一種線程數(shù)目不固定的線程池,它沒(méi)有核心線程,只有非核心線程,當(dāng)線程池中的線程都處于活躍狀態(tài),就會(huì)創(chuàng)建新的線程來(lái)處理新的任務(wù)。否則就會(huì)利用閑置的線程來(lái)處理新的任務(wù)。線程池中的線程都有超時(shí)機(jī)制,這個(gè)超時(shí)機(jī)制時(shí)長(zhǎng)是60s,超過(guò)這個(gè)時(shí)間,閑置的線程就會(huì)被回收。這種線程池適合處理大量并且耗時(shí)較少的任務(wù)。這里得說(shuō)一下,CachedThreadPool的任務(wù)隊(duì)列,基本都是空的。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
ScheduledThreadPool
ScheduledThreadPool線程池是通過(guò)Executors的newScheduledThreadPool進(jìn)行創(chuàng)建的,它的核心線程是固定的,但是非核心線程數(shù)是不固定的,并且當(dāng)非核心線程一處于空閑狀態(tài),就立即被回收。這種線程適合執(zhí)行定時(shí)任務(wù)和具有固定周期的重復(fù)任務(wù)。
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue(), threadFactory);
}
SingleThreadExecutor
SingleThreadExecutor線程池是通過(guò)Executors的newSingleThreadExecutor方法來(lái)創(chuàng)建的,這類線程池中只有一個(gè)核心線程,也沒(méi)有非核心線程,這就確保了所有任務(wù)能夠在同一個(gè)線程并且按照順序來(lái)執(zhí)行,這樣就不需要考慮線程同步的問(wèn)題。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
以上就是分析Android中線程和線程池的詳細(xì)內(nèi)容,更多關(guān)于Android中線程和線程池的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決android studio卡頓,提升studio運(yùn)行速度的方法
這篇文章主要介紹了解決android studio卡頓,提升studio運(yùn)行速度的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03
Android App中讀取XML與JSON格式數(shù)據(jù)的基本方法示例
這篇文章主要介紹了Android App中讀取XML與JSON格式數(shù)據(jù)的基本方法示例,Android中自帶的JSONObject非常好用,需要的朋友可以參考下2016-03-03
Android ksoap調(diào)用webservice批量上傳多張圖片詳解
這篇文章主要介紹了Android ksoap調(diào)用webservice批量上傳多張圖片詳解的相關(guān)資料,需要的朋友可以參考下2017-02-02
Jetpack?Compose實(shí)現(xiàn)點(diǎn)擊事件click的多種方法
這篇文章主要介紹了Jetpack?Compose實(shí)現(xiàn)點(diǎn)擊事件的多種方法,Jetpack?Compose是一款基于Kotlin的聲明式UI工具包,可以方便地創(chuàng)建漂亮的用戶界面,下面我們就來(lái)看看Jetpack?Compose添加點(diǎn)擊事件都可以怎么實(shí)現(xiàn)2024-02-02
Android處理圖像數(shù)據(jù)轉(zhuǎn)換的各種方法
這篇文章主要介紹了Android處理圖像數(shù)據(jù)轉(zhuǎn)換的各種方法,本文講解了RGB值轉(zhuǎn)Bitmap、Color值轉(zhuǎn)Bitmap、字節(jié)數(shù)組轉(zhuǎn)Bitmap、讀取文件轉(zhuǎn)Bitmap、讀取資源轉(zhuǎn)Bitmap、輸入流轉(zhuǎn)Bitmap等內(nèi)容,需要的朋友可以參考下2015-01-01
Android XRecyclerView最簡(jiǎn)單的item點(diǎn)擊事件處理
這篇文章主要為大家詳細(xì)介紹了Android XRecyclerView最簡(jiǎn)單的item點(diǎn)擊事件處理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
Android?中的監(jiān)聽(tīng)和按鍵處理詳情
這篇文章主要介紹了Android?中的監(jiān)聽(tīng)和按鍵處理詳情,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08
Android RecycleView和線型布局制作聊天布局
大家好,本篇文章主要講的是Android RecycleView和線型布局制作聊天布局,感興趣的同學(xué)趕緊來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01

