【Android】线程池
在Android中,主線程不能執(zhí)行耗時(shí)的操作,否則可能會導(dǎo)致ANR。那么,耗時(shí)操作應(yīng)該在其它線程中執(zhí)行。線程的創(chuàng)建和銷毀都會有性能開銷,創(chuàng)建過多的線程也會由于互相搶占系統(tǒng)資源而導(dǎo)致阻塞的現(xiàn)象。這個(gè)時(shí)候,就需要使用線程池。
線程池的優(yōu)點(diǎn)可以概括為以下幾點(diǎn):
1、重用線程池中的線程,避免線程創(chuàng)建、銷毀帶來的性能開銷;
2、能有效地控制線程池的最大并發(fā)數(shù),避免大量的線程之間因互相搶占系統(tǒng)資源導(dǎo)致的阻塞現(xiàn)象;
3、能夠?qū)€程進(jìn)行簡單的管理。
以上線程池的優(yōu)點(diǎn)引用自《Android開發(fā)藝術(shù)探索》
線程池的具體實(shí)現(xiàn)類為ThreadPoolExecutor,ThreadPoolExecutor繼承自AbstractExecutorService,AbstractExecutorService又實(shí)現(xiàn)了ExecutorService接口,ExecutorService繼承自Executor。
ThreadPoolExecutor有四個(gè)重載的構(gòu)造方法:
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler); }public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,threadFactory, defaultHandler); }public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), handler); }public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler; }最終都調(diào)用到了:
/*** Creates a new {@code ThreadPoolExecutor} with the given initial* parameters.** @param corePoolSize the number of threads to keep in the pool, even* if they are idle, unless {@code allowCoreThreadTimeOut} is set* @param maximumPoolSize the maximum number of threads to allow in the* pool* @param keepAliveTime when the number of threads is greater than* the core, this is the maximum time that excess idle threads* will wait for new tasks before terminating.* @param unit the time unit for the {@code keepAliveTime} argument* @param workQueue the queue to use for holding tasks before they are* executed. This queue will hold only the {@code Runnable}* tasks submitted by the {@code execute} method.* @param threadFactory the factory to use when the executor* creates a new thread* @param handler the handler to use when execution is blocked* because the thread bounds and queue capacities are reached* @throws IllegalArgumentException if one of the following holds:<br>* {@code corePoolSize < 0}<br>* {@code keepAliveTime < 0}<br>* {@code maximumPoolSize <= 0}<br>* {@code maximumPoolSize < corePoolSize}* @throws NullPointerException if {@code workQueue}* or {@code threadFactory} or {@code handler} is null*/ public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler; }對應(yīng)這個(gè)方法中的參數(shù):
corePoolSize:核心線程數(shù)。如果沒有設(shè)置allowCoreThreadTimeOut為true,則核心線程空閑時(shí)也不會銷毀。如果設(shè)置allowCoreThreadTimeOut為true,則受keepAliveTime控制,空閑時(shí)間超過keepAliveTime,會被回收。
maximumPoolSize:最大線程數(shù)。
keepAliveTime:非核心線程的空閑超時(shí)時(shí)長。超過這個(gè)時(shí)間,非核心線程會被回收。核心線程如果allowCoreThreadTimeOut為true,則在空閑超過這個(gè)時(shí)間也會被回收。
unit:超時(shí)的單位。
workQueue:線程池中的任務(wù)隊(duì)列。通過線程池的execute()方法提交的Runnable任務(wù)會被放入任務(wù)隊(duì)列中。
threadFactory:線程工廠。
handler:飽和策略。當(dāng)任務(wù)隊(duì)列和線程池都滿后,對新提交的任務(wù)的處理策略。
ThreadPoolExecutor執(zhí)行任務(wù)的規(guī)則:
1、如果線程池中的線程數(shù)量未達(dá)到核心線程數(shù)量,則開啟一個(gè)新的核心線程來執(zhí)行任務(wù);
2、如果線程池中的線程數(shù)量已經(jīng)大于等于核心線程數(shù)量,則會把新的任務(wù)放入任務(wù)隊(duì)列中;
3、如果任務(wù)隊(duì)列已滿,并且線程池中的線程未滿,則開啟非核心線程來處理新的任務(wù);
4、如果任務(wù)隊(duì)列和線程池都已滿,則會交給handler飽和策略來處理。
下面通過一個(gè)簡單的案例來驗(yàn)證以上規(guī)則:
static class WorkThread implements Runnable {private String name;public WorkThread(String name) {this.name = name;}public void run() {try {Thread.sleep(5000);System.out.println("Thread: " + name + " work finish");} catch (Exception e) {e.printStackTrace();}} };Executor executor = new ThreadPoolExecutor(5, 100, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5));for (int i = 0; i < 20; i++) {WorkThread thread = new WorkThread("" + i);executor.execute(thread);}定義了一個(gè)線程池,核心線程池?cái)?shù)量為5,線程數(shù)量為100,超時(shí)時(shí)間為60秒,任務(wù)隊(duì)列為5。在子線程中,sleep 5秒來模擬耗時(shí)的操作。然后開啟了20個(gè)線程,并放入線程池中執(zhí)行。執(zhí)行的結(jié)果如下:
Thread: 0 work finish Thread: 1 work finish Thread: 13 work finish Thread: 10 work finish Thread: 3 work finish Thread: 11 work finish Thread: 4 work finish Thread: 2 work finish Thread: 19 work finish Thread: 18 work finish Thread: 17 work finish Thread: 15 work finish Thread: 16 work finish Thread: 14 work finish Thread: 12 work finish Thread: 5 work finish Thread: 9 work finish Thread: 8 work finish Thread: 7 work finish Thread: 6 work finish前五個(gè)線程在核心線程中執(zhí)行,第6-10個(gè)線程由于核心線程已滿,因此在任務(wù)隊(duì)列中等待執(zhí)行,第11-20個(gè)線程,由于核心線程和隊(duì)列都已滿,而線程池中還可以開啟線程,因此在非核心線程中執(zhí)行。從結(jié)果來看,線程0-4,10-19會先執(zhí)行完,然后任務(wù)隊(duì)列中的線程5-9才執(zhí)行,驗(yàn)證了以上的線程池任務(wù)執(zhí)行規(guī)則。
為便于使用線程池,線程池還有幾種簡便的定義方法:
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()); }public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>()); }public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>())); }public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) {return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); }public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue()); }通過Executors的static方法來創(chuàng)建。其中:
FixedThreadPool:線程數(shù)量固定的線程池。從方法的定義來看,這種線程池里的線程全都是核心線程,并且沒有超時(shí)時(shí)間,任務(wù)隊(duì)列也是沒有限制的。
CachedThreadPool:這種線程池沒有核心線程,全是非核心線程,并且超時(shí)時(shí)間為60秒,任務(wù)隊(duì)列沒有限制。這種線程適合執(zhí)行大量的耗時(shí)較短的任務(wù)。
SingleThreadExecutor:只有一個(gè)核心線程,沒有超時(shí)時(shí)間,任務(wù)隊(duì)列沒有限制。可以確保任務(wù)按順序執(zhí)行。
ScheduledThreadPool:核心線程數(shù)量固定。非核心線程沒有限制。非核心線程閑置時(shí)會被立即回收。這類線程池適合執(zhí)行定時(shí)任務(wù)和具有固定周期的重復(fù)任務(wù)。
轉(zhuǎn)載于:https://www.cnblogs.com/milovetingting/p/10735427.html
總結(jié)
以上是生活随笔為你收集整理的【Android】线程池的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python基础之二进制
- 下一篇: Android中级教程之----Log图