標籤:led 複用 sni 功能 news 核心 單位 ble ret
引入線程池的好處
1)提升效能。建立和消耗對象費時費CPU資源
2)防止記憶體過度消耗。控制活動線程的數量,防止並發線程過多。
我們來看一下線程池的簡單的構造
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {...}使用上面的方式建立線程池的話,我們需要配置一堆東西,非常麻煩,所以我們不建議這麼使用。而是推薦使用Executors的Factory 方法來建立線程池,Executors類是官方提供的一個工廠類,它裡面封裝好了眾多功能不一樣的線程池。下面就介紹幾個常用的線程池。
public ThreadPoolExecutor( //核心線程數,除非allowCoreThreadTimeOut被設定為true,否則它閑著也不會死 int corePoolSize, //最大線程數,活動線程數量超過它,後續任務就會排隊 int maximumPoolSize, //逾時時間長度,作用於非核心線程(allowCoreThreadTimeOut被設定為true時也會同時作用於核心線程),閑置逾時便被回收 long keepAliveTime, //枚舉類型,設定keepAliveTime的單位,有TimeUnit.MILLISECONDS(ms)、TimeUnit. SECONDS(s)等 TimeUnit unit, //緩衝任務隊列,線程池的execute方法會將RunnableObject Storage Service起來 BlockingQueue<Runnable> workQueue, //線程工廠介面,只有一個new Thread(Runnable r)方法,可為線程池建立新線程 ThreadFactory threadFactory)
1、FixedThreadPool() :該方法返回一個固定線程數量的線程池,該線程池中的線程數量始終不變,即不會再建立新的線程,也不會銷毀已經建立好的線程,自始自終都是那幾個固定的線程在工作,所以該線程池可以控制線程的最大並發數。
栗子:假如有一個新任務提交時,線程池中如果有閒置線程則立即使用空閑線程來處理任務,如果沒有,則會把這個新任務存在一個任務隊列中,一旦有線程空閑了,則按FIFO方式處理任務隊列中的任務。
public static ExecutorService newFixThreadPool(int nThreads){ return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } //使用 Executors.newFixThreadPool(5).execute(r);
2、CachedThreadPool() :
該方法返回一個可以根據實際情況調整線程池中線程的數量的線程池。即該線程池中的線程數量不確定,是根據實際情況動態調整的。
栗子:假如該線程池中的所有線程都正在工作,而此時有新任務提交,那麼將會建立新的線程去處理該任務,而此時假如之前有一些線程完成了任務,現在又有新任務提交,那麼將不會建立新線程去處理,而是複用閒置線程去處理新任務。那麼此時有人有疑問了,那這樣來說該線程池的線程豈不是會越集越多?其實並不會,因為線程池中的線程都有一個“保持啟用時間”的參數,通過配置它,如果線程池中的空閑線程的空閑時間超過該“儲存啟用時間”則立刻停止該線程,而該線程池預設的“保持啟用時間”為60s。
public static ExecutorService newCachedThreadPool(int nThreads){ return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit. SECONDS, new SynchronousQueue<Runnable>()); } //使用 Executors.newCachedThreadPool().execute(r);
3、SingleThreadExecutor() :該方法返回一個只有一個線程的線程池,即每次只能執行一個線程任務,多餘的任務會儲存到一個任務隊列中,等待這一個線程空閑,當這個線程空閑了再按FIFO方式順序執行任務隊列中的任務。
public static ExecutorService newSingleThreadPool (int nThreads){ return new FinalizableDelegatedExecutorService ( new ThreadPoolExecutor (1, 1, 0, TimeUnit. MILLISECONDS, new LinkedBlockingQueue<Runnable>()) ); } //使用 Executors.newSingleThreadPool ().execute(r);
4、ScheduledThreadPool() :該方法返回一個可以控制線程池內線程定時或周期性執行某任務的線程池。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize){ return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize){ super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedQueue ()); } //使用,延遲1秒執行,每隔2秒執行一次Runnable r Executors. newScheduledThreadPool (5).scheduleAtFixedRate(r, 1000, 2000, TimeUnit.MILLISECONDS);
自訂線程池Android中常用的線程池就上面的四種,其實在Java中還有一種常見的線程池(newSingleThreadScheduledExecutor),其實上面的線程池對於我們開發已經是足夠了,不過有時候上面的仍然不能滿足我們,這時候我們就需要自訂不同功能的線程池。上面我們也說了線程池功能的不同歸根到底還是內部的BlockingQueue實現不同,所以,我們要實現我們自己相要的線程池,就必須從BlockingQueue的實現上做手腳。那麼我們接下來就用PriorityBlockingQueue來實現一個FIFO的線程池。
1)建立一個基於PriorityBlockingQueue的線程池
ExecutorService priorityThreadPool = new ThreadPoolExecutor(3,3,0L,TimeUnit.SECONDS,new PriorityBlockingQueue());
2)建立一個實現Runnable介面的類,並向外提供我們實現自訂功能,並實現Comparable介面
public abstract class PriorityRunnable implements Runnable, Comparable { private int priority; public PriorityRunnable(int priority) { if (priority 0) throw new IllegalArgumentException(); this.priority = priority; } @Override public int compareTo(PriorityRunnable another) { int my = this.getPriority(); int other = another.getPriority(); return my 1 : my > other ? -1 : 0; } @Override public void run() { doSth(); } public abstract void doSth(); public int getPriority() { return priority; }}
3)使用PriorityRunnable提交任務
ExecutorService priorityThreadPool = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.SECONDS, new PriorityBlockingQueue()); for (int i = 1; i 10; i++) { final int priority = i; priorityThreadPool.execute(new PriorityRunnable(priority) { @Override public void doSth() { String threadName = Thread.currentThread().getName(); Log.v("zxy", "線程:" + threadName + ",正在執行優先順序為:" + priority + "的任務"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }); }
Android 四種常見的線程池