筆記:Android線程和線程池

Android線程和線程池

  • Android中的線程操作相關(guān)的類有

AsyncTask IntentService HandleThread

  • AsyncTask
  • AsyncTask必須在主線程中初始化

  • Android 3.0開始 AsyncTask默認(rèn)使用串行方式執(zhí)行任務(wù)隊(duì)列惹盼,即單線程串行簿训,但可定制線程池并行執(zhí)行通過executOnExecutor()傲宜。

主要是SerialExcutor負(fù)責(zé)任務(wù)的排隊(duì)星立,THREAD_POOL_EXCUTOR負(fù)責(zé)真正的任務(wù)執(zhí)行经瓷。

  • executor()方法必須在UI線程中執(zhí)行

  • 一個(gè)AsyncTask對象只能執(zhí)行一次痹届,否則會(huì)報(bào)錯(cuò)

  • AsyncTask中有用到抽象工廠模式(多線程環(huán)境下工廠類創(chuàng)建線程)

  • AsyncTask中對任務(wù)包裝主要是FutureTask

FutureTask可用于異步獲取執(zhí)行結(jié)果或取消執(zhí)行任務(wù)的場景魄眉。通過傳入Runnable或者Callable的任務(wù)給FutureTask鬼廓,直接調(diào)用其run方法或者放入線程池執(zhí)行晰奖,之后可以在外部通過FutureTask的get方法異步獲取執(zhí)行結(jié)果谈撒,因此,F(xiàn)utureTask非常適合用于耗時(shí)的計(jì)算匾南,主線程可以在完成自己的任務(wù)后啃匿,再去獲取結(jié)果。另外蛆楞,F(xiàn)utureTask還可以確保即使調(diào)用了多次run方法溯乒,它都只會(huì)執(zhí)行一次Runnable或者Callable任務(wù),或者通過cancel取消FutureTask的執(zhí)行等豹爹。


  • HandleThread

繼承自Thread,主要是內(nèi)部創(chuàng)建了Looper裆悄,關(guān)聯(lián)Looper,不用手動(dòng)創(chuàng)建Thread中prepare Looper和loop了臂聋。


  • IntentService

一個(gè)抽象類光稼,繼承自Service

適用于執(zhí)行后臺耗時(shí)任務(wù)崖技,任務(wù)停止后,Service自動(dòng)停止

由于它是服務(wù)钟哥,它比其他線程優(yōu)先級高很多迎献,不容易被系統(tǒng)kill

內(nèi)部它封裝了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);
    }

  • IntentSerivce 通過調(diào)用startService傳遞Intent到onStartCommand,onStartCommand會(huì)通過Handle發(fā)送Message至IntentService內(nèi)部的HandleThread中腻贰,根據(jù)Intent
    中攜帶的參數(shù)吁恍,調(diào)用重寫的onHandleIntent處理任務(wù),onHandleIntent執(zhí)行完畢后播演,執(zhí)行stopSelf(startId)
這里為何調(diào)用stopSelf(startId) 它與stopSelf()區(qū)別

stopSelf(startId)不會(huì)立即停止當(dāng)前Serivce,而是等待所有Intent都執(zhí)行完畢后才會(huì)終止服務(wù)冀瓦,每調(diào)用一次startService(Intent)都會(huì)調(diào)用一次onStartCommand傳遞Intent。

stopSelf()會(huì)立即停止服務(wù)


  • 因?yàn)镮ntentService內(nèi)部HandleThread的消息機(jī)制写烤,所以翼闽,傳遞給IntentService的Intent任務(wù)也是順序執(zhí)行的。

Android中的線程池

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) 

corePoolSize: 核心線程數(shù)洲炊,默認(rèn)情況下一直存活的線程感局,即使空閑狀態(tài)下,如果將ThreadPoolExecutor的allowCoreThreadTimeOut屬性設(shè)置為true暂衡,則閑置的線程在等待新任務(wù)到來時(shí)會(huì)有超時(shí)策略询微,超時(shí)時(shí)間由keepAliveTime來決定,當(dāng)超時(shí)后狂巢,核心線程就會(huì)被終止

maximumPoolSize: 線程池所能容納的最大線程數(shù)撑毛,當(dāng)活動(dòng)線程數(shù)達(dá)到這個(gè)數(shù)值后,后續(xù)的新任務(wù)將會(huì)被阻塞

keepAliveTime:非核心線程線程閑置時(shí)間超時(shí)時(shí)長唧领。超過這個(gè)時(shí)長藻雌,線程將會(huì)被回收

unit:指定keepAliveTime所用的時(shí)間單位

workQueue:線程池中的任務(wù)隊(duì)列,通過execute提交的Runnable對象會(huì)存儲在這個(gè)隊(duì)列中斩个。

threadFactory:線程工廠胯杭,為線程池創(chuàng)建新的線程,為一個(gè)接口萨驶。


  • ThreadpoolExecutor 執(zhí)行任務(wù)大致規(guī)則:
  1. 如果線程池中的核心線程數(shù)未達(dá)到核心線程的數(shù)量歉摧,那么會(huì)啟動(dòng)核心線程來執(zhí)行任務(wù)艇肴。
  2. 如果線程池中的線程數(shù)量已經(jīng)達(dá)到或超過核心線程數(shù)量腔呜,那么新來的任務(wù)會(huì)被插入到任務(wù)隊(duì)列中排隊(duì)等待執(zhí)行
  3. 如果在步驟2中無法將任務(wù)插入到任務(wù)隊(duì)列,這是由于任務(wù)隊(duì)列已經(jīng)滿了再悼,這個(gè)時(shí)候如果線程數(shù)量未達(dá)到線程池規(guī)定的最大數(shù)量核畴,那么會(huì)立刻啟動(dòng)一個(gè)非核心線程來執(zhí)行任務(wù)。
  4. 如果步驟3中的線程數(shù)量已經(jīng)達(dá)到線程池的最大值冲九,則拒絕此任務(wù)谤草,ThreadPoolExecutor會(huì)調(diào)用RejectedExecutionHandler的rejectExecution方法通知調(diào)用者跟束。具體可以看源碼.

  • AsyncTask中的任務(wù)隊(duì)列容量為128

  • Android中四種常用的線程池:
  1. FixedThreadPool

    Executors.newFixedThreadPool()

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

線程數(shù)量固定,當(dāng)線程處于空閑時(shí)丑孩,線程并不會(huì)被回收冀宴,除非線程池關(guān)閉,當(dāng)所有線程處于活動(dòng)狀態(tài)時(shí)温学,新任務(wù)就會(huì)處于等待狀態(tài)略贮,直到有線程空閑下來.

由于FixedThreadPool只有核心線程,并且不會(huì)被??仗岖,所以它會(huì)更加快速的響應(yīng)外界的請求逃延。沒有超時(shí)機(jī)制,任務(wù)隊(duì)列大小也沒閑置轧拄。

  1. CachedThreadPool

    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
                                      

它是一個(gè)線程數(shù)量不固定的線程池揽祥,當(dāng)線程池中的線程都處于活動(dòng)狀態(tài),線程池會(huì)創(chuàng)建新的線程來處理任務(wù)檩电,否者就會(huì)利用空閑的線程來處理新任務(wù)

空閑的線程超過60秒就會(huì)被回收

SynchronousQueue很特殊拄丰,無法存儲元素的隊(duì)列。

該線程池適合大量耗時(shí)較少的任務(wù)俐末,當(dāng)整個(gè)線程池中的線程都處于空閑狀態(tài)時(shí)愈案,線程會(huì)因超時(shí)而被??,這時(shí)它幾乎不占用任何資源

  1. ScheduledThreadPoolExecutor

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

核心線程數(shù)固定鹅搪,非核心線程數(shù)沒有限制站绪,當(dāng)非核心線程空閑會(huì)被立刻回收

適合執(zhí)行定時(shí)任務(wù)和有固定周期的重復(fù)任務(wù)

參考最后使用示例

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

只有一個(gè)核心線程,所有的任務(wù)都會(huì)放到一個(gè)線程中去順序執(zhí)行

它統(tǒng)一了所有的外界任務(wù)到一個(gè)線程中丽柿,使得這些任務(wù)不需要處理線程間的同步問題恢准。


  • 使用示例
Runnable command = new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(1000);
            }
        };

        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
        fixedThreadPool.execute(command);

        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        cachedThreadPool.execute(command);

        //2000ms后執(zhí)行command
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
        scheduledExecutorService.schedule(command, 2000, TimeUnit.MILLISECONDS);

        //延遲10ms后執(zhí)行,以后每隔1000ms執(zhí)行一次command
        scheduledExecutorService.scheduleAtFixedRate(command, 10, 1000, TimeUnit.MILLISECONDS);

        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        singleThreadExecutor.execute(command);

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甫题,一起剝皮案震驚了整個(gè)濱河市馁筐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坠非,老刑警劉巖敏沉,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異炎码,居然都是意外死亡盟迟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門潦闲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來攒菠,“玉大人,你說我怎么就攤上這事歉闰∠街冢” “怎么了卓起?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長凹炸。 經(jīng)常有香客問我戏阅,道長,這世上最難降的妖魔是什么啤它? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任饲握,我火速辦了婚禮,結(jié)果婚禮上蚕键,老公的妹妹穿的比我還像新娘救欧。我一直安慰自己,他們只是感情好锣光,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布笆怠。 她就那樣靜靜地躺著,像睡著了一般誊爹。 火紅的嫁衣襯著肌膚如雪蹬刷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天频丘,我揣著相機(jī)與錄音办成,去河邊找鬼。 笑死搂漠,一個(gè)胖子當(dāng)著我的面吹牛迂卢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播桐汤,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼而克,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了怔毛?” 一聲冷哼從身側(cè)響起员萍,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拣度,沒想到半個(gè)月后碎绎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抗果,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年筋帖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窖张。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡幕随,死狀恐怖蚁滋,靈堂內(nèi)的尸體忽然破棺而出宿接,到底是詐尸還是另有隱情赘淮,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布睦霎,位于F島的核電站梢卸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏副女。R本人自食惡果不足惜蛤高,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望碑幅。 院中可真熱鬧戴陡,春花似錦、人聲如沸沟涨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽裹赴。三九已至喜庞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間棋返,已是汗流浹背延都。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睛竣,地道東北人晰房。 一個(gè)月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像射沟,于是被迫代替她去往敵國和親嫉你。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android中的線程 線程躏惋,在Android中是非常重要的幽污,主線程處理UI界面,子線程處理耗時(shí)操作簿姨。如果在主線程...
    shenhuniurou閱讀 748評論 0 3
  • 從用途上來說距误,線程分為主線程和子線程,主線程主要處理和界面相關(guān)的事情扁位,子線程則往往用于執(zhí)行耗時(shí)操作准潭。 除了Thre...
    小柏不是大白閱讀 624評論 0 3
  • 來自野火無盡生第69天作業(yè)刑然, 《說說自己對香水的看法》,想起來一個(gè)說法暇务,說是香水在法國得到了大發(fā)展泼掠,是因?yàn)槟菚r(shí)候人...
    野火無盡生閱讀 140評論 0 0
  • Spring提供了三種裝配的機(jī)制: 自動(dòng)化裝配Bean 通過Java進(jìn)行顯式配置 在XML中進(jìn)行配置 1.自動(dòng)化裝...
    悠揚(yáng)前奏閱讀 369評論 0 1
  • 為你千千萬萬遍怔软,是生命中不可承受之重。 電影《追風(fēng)箏的人》中哈桑的一句話打動(dòng)了很多人择镇。阿米爾和哈桑比的確是個(gè)壞小孩...
    小倩星閱讀 317評論 0 55