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余指。
- FixedThreadPool 只有核心線程,并且數(shù)量是固定的跷坝,也不會被回收酵镜,能更快地響應外界請求。
- SingleThreadPool 只有一個核心線程柴钻,確保所有任務都在同一線程中按順序完成淮韭。因此不需要處理線程同步的問題。
- CachedThreadPool 只有非核心線程贴届,最大線程數(shù)非常大靠粪,所有線程都活動時,會為新任務創(chuàng)建新線程毫蚓,否則利用空閑線程處理任務占键,任何任務都會被立即執(zhí)行。
- 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