Android 線程池的封裝

GlobalThreadPools.java:

/**
 * 全局使用的線程池
 */
public class GlobalThreadPools {

    private static String TAG = GlobalThreadPools.class.getSimpleName();

    private static ExecutorService THREAD_POOL_EXECUTOR;//線程池

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();//CPU數(shù)量
    private static final int CORE_POOL_SIZE = CPU_COUNT;//核心線程數(shù)
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2;//最大線程數(shù)
    private static final int KEEP_ALIVE_SECONDS = 60;//線程閑置后的存活時間
    private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<>(CPU_COUNT);//任務隊列
    private static final ThreadFactory sThreadFactory = new ThreadFactory() {//線程工廠
        private final AtomicInteger mCount = new AtomicInteger(1);
        public Thread newThread(Runnable r) {
            return new Thread(r, "MangoTask #" + mCount.getAndIncrement());
        }
    };

    //初始化線程池
    private void initThreadPool() {
        THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory, new RejectedHandler()){
            @Override
            public void execute(Runnable command) {
                super.execute(command);
                Log.e(TAG,"ActiveCount="+getActiveCount());
                Log.e(TAG,"PoolSize="+getPoolSize());
                Log.e(TAG,"Queue="+getQueue().size());
            }
        };
    }

    private static class RejectedHandler implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            //可在這里做一些提示用戶的操作
//            Log.v("+++","is over the max task...");
        }
    }

    private static GlobalThreadPools instance;
    private GlobalThreadPools(){
        initThreadPool();
    }
    public static GlobalThreadPools getInstance(){
        if (instance == null) {
            instance = new GlobalThreadPools();
        }
        return instance;
    }

    public void execute(Runnable command){
        THREAD_POOL_EXECUTOR.execute(command);
    }

//    /**
//     * 通過interrupt方法嘗試停止正在執(zhí)行的任務,但是不保證真的終止正在執(zhí)行的任務
//     * 停止隊列中處于等待的任務的執(zhí)行
//     * 不再接收新的任務
//     * @return 等待執(zhí)行的任務列表
//     */
//    public List<Runnable> shutdownNow(){
//        return THREAD_POOL_EXECUTOR.shutdownNow();
//    }
//
//    /**
//     * 停止隊列中處于等待的任務
//     * 不再接收新的任務
//     * 已經(jīng)執(zhí)行的任務會繼續(xù)執(zhí)行
//     * 如果任務已經(jīng)執(zhí)行完了沒有必要再調(diào)用這個方法
//     */
//    public void shutDown(){
//        THREAD_POOL_EXECUTOR.shutdown();
//        sPoolWorkQueue.clear();
//    }

}

調(diào)用:

//線程池開啟任務
        GlobalThreadPools.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                  .......
            }
        });

線程池
線程池概念來源于Java中的Executor,它是一個接口,真正的實現(xiàn)為ThreadPoolExecutor贸辈。ThreadPoolExecutor提供了一系列參數(shù)來配置線程池。
優(yōu)點
1:重用線程池中的線程,線程在執(zhí)行完任務后不會立刻銷毀,而會等待另外的任務,這樣就不會頻繁地創(chuàng)建曹铃、銷毀線程和調(diào)用GC缰趋。。
2:有效控制線程池的最大并發(fā)數(shù)陕见,避免大量線程搶占資源出現(xiàn)的問題秘血。
3:對多個線程進行統(tǒng)一地管理,可提供定時執(zhí)行及指定間隔循環(huán)執(zhí)行的功能评甜。
ThreadPoolExecutor 有多個重載方法灰粮,但最終都調(diào)用了這個構(gòu)造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
參數(shù):
corePoolSize:線程池中核心線程的數(shù)量;為了內(nèi)存優(yōu)化忍坷,在線程池維護了幾個重要的線程粘舟,不達到一定條件不開辟其余線程
maximumPoolSize :線程池中最大線程數(shù)量:這個數(shù)量是包括核心線程的,當線程池中的正在執(zhí)行的線程池達到了這個數(shù)字佩研,再提交線程如果你不做特殊處理將會拋出異常
keepAliveTime:非核心線程的超時時長柑肴;當線程池中的非核心線程閑置時間超過這個值代表的時間后,將會被回收旬薯;同時如果調(diào)用ThreadPoolExecutor.allowCoreThreadTimeOut(true)晰骑,那么核心線程也會符合這個設(shè)置
unit:keepAliveTime值的單位,可以是時分秒等
workQueue:存放待執(zhí)行的線程绊序;你通過execute方法提交線程硕舆,但是這些線程還沒達到執(zhí)行條件,那么就會保存在這個隊列里
threadFactory:創(chuàng)建線程池的工廠骤公;在這個工廠里抚官,我們可以指定線程的一些信息
handler:線程提交拒絕策略;通常是線程池中的正在執(zhí)行的線程數(shù)量已經(jīng)達到了最大線程數(shù)或線程池關(guān)閉阶捆,如果不傳耗式,默認是拋出一個RejectedExecutionException,所以最好傳下

推薦使用 Executors 的工廠方法來創(chuàng)建線程池,通過直接或間接的配置 ThreadPoolExecutor 的參數(shù)來構(gòu)建線程池刊咳,常用的線程池有如下 4 種彪见,newFixedThreadPool ,newCachedThreadPool娱挨,
newScheduledThreadPool 和 newSingleThreadExecutor余指。

  1. FixedThreadPool 只有核心線程,并且數(shù)量是固定的跷坝,也不會被回收酵镜,能更快地響應外界請求。
  2. SingleThreadPool 只有一個核心線程柴钻,確保所有任務都在同一線程中按順序完成淮韭。因此不需要處理線程同步的問題。
  3. CachedThreadPool 只有非核心線程贴届,最大線程數(shù)非常大靠粪,所有線程都活動時,會為新任務創(chuàng)建新線程毫蚓,否則利用空閑線程處理任務占键,任何任務都會被立即執(zhí)行。
  4. ScheduledThreadPool 核心線程數(shù)固定元潘,非核心線程數(shù)沒有限制畔乙,主要用于執(zhí)行定時任務以及有固定周期的重復任務。

ThreadPoolExecutor 執(zhí)行任務時大致遵循如下流程:
1.如果線程池中的線程數(shù)未達到核心線程數(shù)翩概,則會立馬啟用一個核心線程去執(zhí)行牲距。
2.如果線程池中的線程數(shù)已經(jīng)達到核心線程數(shù),且任務隊列workQueue未滿钥庇,則將新線程放入workQueue中等待執(zhí)行嗅虏。
3.如果線程池中的線程數(shù)已經(jīng)達到核心線程數(shù)但未超過線程池規(guī)定最大值,且workQueue已滿上沐,則開啟一個非核心線程來執(zhí)行任務皮服。
4.如果線程池中的線程數(shù)已經(jīng)超過線程池規(guī)定最大值,則拒絕執(zhí)行該任務参咙,采取飽和策略龄广,并拋出RejectedExecutionException異常。

線程池大性滩唷:(N為CPU數(shù)量)
如果是CPU密集型應用择同,則線程池大小設(shè)置為N+1
如果是IO密集型應用,則線程池大小設(shè)置為2N+1
I/O密集型
指的是系統(tǒng)的CPU效能相對硬盤/內(nèi)存的效能要好净宵,大部分的狀況是 CPU 在等 I/O (硬盤/內(nèi)存) 的讀/寫敲才, CPU Loading 不高裹纳。
CPU密集型
指的是系統(tǒng)的 硬盤/內(nèi)存 效能 相對 CPU 的效能 要好,大部分的狀況是 CPU Loading 100%紧武,CPU 要讀/寫 I/O (硬盤/內(nèi)存)剃氧,I/O在很短的時間就可以完成,而 CPU 還有許多運算要處理阻星,CPU Loading 很高朋鞍。
獲取CPU數(shù)量的方法為:
Runtime.getRuntime().availableProcessors();

摘自:
https://blog.csdn.net/qq_30993595/article/details/84324681

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市妥箕,隨后出現(xiàn)的幾起案子滥酥,更是在濱河造成了極大的恐慌,老刑警劉巖畦幢,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坎吻,死亡現(xiàn)場離奇詭異,居然都是意外死亡宇葱,警方通過查閱死者的電腦和手機瘦真,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贝搁,“玉大人,你說我怎么就攤上這事芽偏±啄妫” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵污尉,是天一觀的道長膀哲。 經(jīng)常有香客問我,道長被碗,這世上最難降的妖魔是什么某宪? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮锐朴,結(jié)果婚禮上兴喂,老公的妹妹穿的比我還像新娘。我一直安慰自己焚志,他們只是感情好衣迷,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著酱酬,像睡著了一般壶谒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上膳沽,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天汗菜,我揣著相機與錄音让禀,去河邊找鬼。 笑死陨界,一個胖子當著我的面吹牛巡揍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播普碎,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吼肥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了麻车?” 一聲冷哼從身側(cè)響起缀皱,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎动猬,沒想到半個月后啤斗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡赁咙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年钮莲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片彼水。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡崔拥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凤覆,到底是詐尸還是另有隱情链瓦,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布盯桦,位于F島的核電站慈俯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏拥峦。R本人自食惡果不足惜贴膘,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望略号。 院中可真熱鬧刑峡,春花似錦、人聲如沸玄柠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽随闪。三九已至阳似,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間铐伴,已是汗流浹背撮奏。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工俏讹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人畜吊。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓泽疆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親玲献。 傳聞我的和親對象是個殘疾皇子殉疼,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355