日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android 线程池

發(fā)布時(shí)間:2023/11/29 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 线程池 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

為什么用線程池

創(chuàng)建/銷毀線程伴隨著系統(tǒng)開銷,過于頻繁的創(chuàng)建/銷毀線程,會(huì)很大程度上影響處理效率

例如:

  • 記創(chuàng)建線程消耗時(shí)間T1,執(zhí)行任務(wù)消耗時(shí)間T2,銷毀線程消耗時(shí)間T3

如果T1+T3>T2,那么是不是說開啟一個(gè)線程來執(zhí)行這個(gè)任務(wù)太不劃算了!

正好,線程池緩存線程,可用已有的閑置線程來執(zhí)行新任務(wù),避免了T1+T3帶來的系統(tǒng)開銷

  • 線程并發(fā)數(shù)量過多,搶占系統(tǒng)資源從而導(dǎo)致阻塞
    我們知道線程能共享系統(tǒng)資源,如果同時(shí)執(zhí)行的線程過多,就有可能導(dǎo)致系統(tǒng)資源不足而產(chǎn)生阻塞的情況,運(yùn)用線程池能有效的控制線程最大并發(fā)數(shù),避免以上的問題

  • 對(duì)線程進(jìn)行一些簡(jiǎn)單的管理
    比如:延時(shí)執(zhí)行、定時(shí)循環(huán)執(zhí)行的策略等
    運(yùn)用線程池都能進(jìn)行很好的實(shí)現(xiàn)

線程池ThreadPoolExecutor

既然Android中線程池來自于Java,那么研究Android線程池其實(shí)也可以說是研究Java中的線程池

在Java中,線程池的概念是Executor這個(gè)接口,具體實(shí)現(xiàn)為ThreadPoolExecutor類,學(xué)習(xí)Java中的線程池,就可以直接學(xué)習(xí)他了

對(duì)線程池的配置,就是對(duì)ThreadPoolExecutor構(gòu)造函數(shù)的參數(shù)的配置,既然這些參數(shù)這么重要,就來看看構(gòu)造函數(shù)的各個(gè)參數(shù)吧

ThreadPoolExecutor提供了四個(gè)構(gòu)造函數(shù)

//五個(gè)參數(shù)的構(gòu)造函數(shù)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue)

//六個(gè)參數(shù)的構(gòu)造函數(shù)-1
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory)

//六個(gè)參數(shù)的構(gòu)造函數(shù)-2
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
RejectedExecutionHandler handler)

//七個(gè)參數(shù)的構(gòu)造函數(shù)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)

我知道你看到這些構(gòu)造函數(shù)和我一樣也是嚇呆了,但其實(shí)一共就7種類型,理解起來簡(jiǎn)直和理解一周有7天一樣簡(jiǎn)單,而且一周有兩天是周末,其實(shí)也就只有5天需要了解!相信我,畢竟扯皮,我比較擅長

int corePoolSize => 該線程池中核心線程數(shù)最大值

核心線程:

線程池新建線程的時(shí)候,如果當(dāng)前線程總數(shù)小于corePoolSize,則新建的是核心線程,如果超過corePoolSize,則新建的是非核心線程

核心線程默認(rèn)情況下會(huì)一直存活在線程池中,即使這個(gè)核心線程啥也不干(閑置狀態(tài))。

如果指定ThreadPoolExecutor的allowCoreThreadTimeOut這個(gè)屬性為true,那么核心線程如果不干活(閑置狀態(tài))的話,超過一定時(shí)間(時(shí)長下面參數(shù)決定),就會(huì)被銷毀掉

很好理解吧,正常情況下你不干活我也養(yǎng)你,因?yàn)槲铱傆杏玫侥愕臅r(shí)候,但有時(shí)候特殊情況(比如我自己都養(yǎng)不起了),那你不干活我就要把你干掉了
int maximumPoolSize

該線程池中線程總數(shù)最大值

線程總數(shù) = 核心線程數(shù) + 非核心線程數(shù)。核心線程在上面解釋過了,這里說下非核心線程:

不是核心線程的線程,在上面解釋過了
long keepAliveTime

該線程池中非核心線程閑置超時(shí)時(shí)長

一個(gè)非核心線程,如果不干活(閑置狀態(tài))的時(shí)長超過這個(gè)參數(shù)所設(shè)定的時(shí)長,就會(huì)被銷毀掉

如果設(shè)置allowCoreThreadTimeOut = true,則會(huì)作用于核心線程
TimeUnit unit

keepAliveTime的單位,TimeUnit是一個(gè)枚舉類型,其包括:

NANOSECONDS : 1微毫秒 = 1微秒 / 1000
MICROSECONDS : 1微秒 = 1毫秒 / 1000
MILLISECONDS : 1毫秒 = 1秒 /1000
SECONDS : 秒
MINUTES : 分
HOURS : 小時(shí)
DAYS : 天
BlockingQueue workQueue

該線程池中的任務(wù)隊(duì)列:維護(hù)著等待執(zhí)行的Runnable對(duì)象

當(dāng)所有的核心線程都在干活時(shí),新添加的任務(wù)會(huì)被添加到這個(gè)隊(duì)列中等待處理,如果隊(duì)列滿了,則新建非核心線程執(zhí)行任務(wù)

常用的workQueue類型:

SynchronousQueue:這個(gè)隊(duì)列接收到任務(wù)的時(shí)候,會(huì)直接提交給線程處理,而不保留它,如果所有線程都在工作怎么辦?那就新建一個(gè)線程來處理這個(gè)任務(wù)!所以為了保證不出現(xiàn)<線程數(shù)達(dá)到了maximumPoolSize而不能新建線程>的錯(cuò)誤,使用這個(gè)類型隊(duì)列的時(shí)候,maximumPoolSize一般指定成Integer.MAX_VALUE,即無限大

LinkedBlockingQueue:這個(gè)隊(duì)列接收到任務(wù)的時(shí)候,如果當(dāng)前線程數(shù)小于核心線程數(shù),則新建線程(核心線程)處理任務(wù);如果當(dāng)前線程數(shù)等于核心線程數(shù),則進(jìn)入隊(duì)列等待。由于這個(gè)隊(duì)列沒有最大值限制,即所有超過核心線程數(shù)的任務(wù)都將被添加到隊(duì)列中,這也就導(dǎo)致了maximumPoolSize的設(shè)定失效,因?yàn)榭偩€程數(shù)永遠(yuǎn)不會(huì)超過corePoolSize

ArrayBlockingQueue:可以限定隊(duì)列的長度,接收到任務(wù)的時(shí)候,如果沒有達(dá)到corePoolSize的值,則新建線程(核心線程)執(zhí)行任務(wù),如果達(dá)到了,則入隊(duì)等候,如果隊(duì)列已滿,則新建線程(非核心線程)執(zhí)行任務(wù),又如果總線程數(shù)到了maximumPoolSize,并且隊(duì)列也滿了,則發(fā)生錯(cuò)誤

DelayQueue:隊(duì)列內(nèi)元素必須實(shí)現(xiàn)Delayed接口,這就意味著你傳進(jìn)去的任務(wù)必須先實(shí)現(xiàn)Delayed接口。這個(gè)隊(duì)列接收到任務(wù)時(shí),首先先入隊(duì),只有達(dá)到了指定的延時(shí)時(shí)間,才會(huì)執(zhí)行任務(wù)
ThreadFactory threadFactory創(chuàng)建線程的方式,這是一個(gè)接口,你new他的時(shí)候需要實(shí)現(xiàn)他的Thread newThread(Runnable r)方法

小伙伴應(yīng)該知道AsyncTask是對(duì)線程池的封裝吧?那就直接放一個(gè)AsyncTask新建線程池的threadFactory參數(shù)源碼吧:

new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);

public Thread new Thread(Runnable r) {return new Thread(r,"AsyncTask #" + mCount.getAndIncrement()); }

}
這么簡(jiǎn)單?就給線程起了個(gè)名?
RejectedExecutionHandler handler

這玩意兒就是拋出異常專用的,比如上面提到的兩個(gè)錯(cuò)誤發(fā)生了,就會(huì)由這個(gè)handler拋出異常,你不指定他也有個(gè)默認(rèn)的

新建一個(gè)線程池的時(shí)候,一般只用5個(gè)參數(shù)的構(gòu)造函數(shù)。

向ThreadPoolExecutor添加任務(wù)

那說了這么多,你可能有疑惑,我知道new一個(gè)ThreadPoolExecutor,大概知道各個(gè)參數(shù)是干嘛的,可是我new完了,怎么向線程池提交一個(gè)要執(zhí)行的任務(wù)啊?

通過ThreadPoolExecutor.execute(Runnable command)方法即可向線程池內(nèi)添加一個(gè)任務(wù)

ThreadPoolExecutor的策略

上面介紹參數(shù)的時(shí)候其實(shí)已經(jīng)說到了ThreadPoolExecutor執(zhí)行的策略,這里給總結(jié)一下,當(dāng)一個(gè)任務(wù)被添加進(jìn)線程池時(shí):

線程數(shù)量未達(dá)到corePoolSize,則新建一個(gè)線程(核心線程)執(zhí)行任務(wù)
線程數(shù)量達(dá)到了corePools,則將任務(wù)移入隊(duì)列等待
隊(duì)列已滿,新建線程(非核心線程)執(zhí)行任務(wù)
隊(duì)列已滿,總線程數(shù)又達(dá)到了maximumPoolSize,就會(huì)由上面RejectedExecutionHandler拋出異常
常見四種線程池

如果你不想自己寫一個(gè)線程池,那么你可以從下面看看有沒有符合你要求的(一般都?jí)蛴昧?,如果有,那么很好你直接用就行了,如果沒有,那你就老老實(shí)實(shí)自己去寫一個(gè)吧

Java通過Executors提供了四種線程池,這四種線程池都是直接或間接配置ThreadPoolExecutor的參數(shù)實(shí)現(xiàn)的,下面我都會(huì)貼出這四種線程池構(gòu)造函數(shù)的源碼,各位大佬們一看便知!

來,走起:

CachedThreadPool()

可緩存線程池:

線程數(shù)無限制
有空閑線程則復(fù)用空閑線程,若無空閑線程則新建線程
一定程序減少頻繁創(chuàng)建/銷毀線程,減少系統(tǒng)開銷
創(chuàng)建方法:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

源碼:

public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
通過我上面行云流水談笑風(fēng)生天馬行空滔滔不絕的對(duì)各種參數(shù)的說明,這個(gè)源碼你肯定一眼就看懂了,想都不用想(下面三種一樣啦)

FixedThreadPool()

定長線程池:

可控制線程最大并發(fā)數(shù)(同時(shí)執(zhí)行的線程數(shù))
超出的線程會(huì)在隊(duì)列中等待
創(chuàng)建方法:

//nThreads => 最大線程數(shù)即maximumPoolSize
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(int nThreads);

//threadFactory => 創(chuàng)建線程的方法
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(int nThreads, ThreadFactory threadFactory);
源碼:

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

定長線程池:

支持定時(shí)及周期性任務(wù)執(zhí)行。
創(chuàng)建方法:

//nThreads => 最大線程數(shù)即maximumPoolSize
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(int corePoolSize);
源碼:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}

//ScheduledThreadPoolExecutor():
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
SingleThreadExecutor()

單線程化的線程池:

有且僅有一個(gè)工作線程執(zhí)行任務(wù)
所有任務(wù)按照指定順序執(zhí)行,即遵循隊(duì)列的入隊(duì)出隊(duì)規(guī)則
創(chuàng)建方法:

ExecutorService singleThreadPool = Executors.newSingleThreadPool();

總結(jié)

以上是生活随笔為你收集整理的android 线程池的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。