Android效能最佳化之使用線程池
在寫程式時有些非同步程式只執行一遍就不需要了,為了方便經常會寫下面的代碼
new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub }}).start();
這樣new出來的匿名對象會存在一些問題
1.由於是匿名的,無法對它進行管理
2.如果需要多次執行這個操作就new多次,可能建立多個,佔用系統資源
3.無法執行更多的操作
使用線程池的好處
1.可以重複利用存在的線程,減少系統的開銷
2.利用線程池可以執行定時、並發數的控制
Java的線程池對Android也是適用的
線程池的作用:
線程池作用就是限制系統中執行線程的數量。
根據系統的環境情況,可以自動或手動設定線程數量,達到啟動並執行最佳效果;少了浪費了系統資源,多了造成系統擁擠效率不高。用線程池控制線程數量,其他線程排隊等候。一個任務執行完畢,再從隊列的中取最前面的任務開始執行。若隊列中沒有等待進程,線程池的這一資源處於等待。當一個新任務需要運行時,如果線程池中有等待的背景工作執行緒,就可以開始運行了;否則進入等待隊列。
為什麼要用線程池:
1.減少了建立和銷毀線程的次數,每個背景工作執行緒都可以被重複利用,可執行多個任務。
2.可以根據系統的承受能力,調整線程池中工作線線程的數目,防止因為消耗過多的記憶體,而把伺服器累趴下(每個線程需要大約1MB記憶體,線程開的越多,消耗的記憶體也就越大,最後死機)。
Java通過Executors提供四種線程池,分別為:
newCachedThreadPool建立一個可緩衝線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則建立線程。
newFixedThreadPool 建立一個定長線程池,可控制線程最大並發數,超出的線程會在隊列中等待。
newScheduledThreadPool 建立一個定長線程池,支援定時及週期性任務執行。
newSingleThreadExecutor 建立一個單線程化的線程池,它只會用唯一的背景工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
1.newCachedThreadPool
/** * 可以緩衝線程池 */public static void Function1() {ExecutorService executorService = Executors.newCachedThreadPool();for (int i = 0; i < 50; i++) {final int index = i;try {Thread.sleep(100); // 休眠時間越短建立的線程數越多} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}executorService.execute(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubSystem.out.println("active count = " + Thread.activeCount()+ " index = " + index);try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}});}}
列印結果
active count = 2 index = 0
active count = 3 index = 1
active count = 4 index = 2
active count = 5 index = 3
active count = 6 index = 4
active count = 7 index = 5
active count = 8 index = 6
active count = 9 index = 7
active count = 10 index = 8
active count = 11 index = 9
active count = 11 index = 10
active count = 11 index = 11
active count = 11 index = 12
active count = 11 index = 13
active count = 11 index = 14
active count = 11 index = 15
active count = 11 index = 16
active count = 11 index = 17
active count = 11 index = 18
active count = 11 index = 19
active count = 11 index = 20
active count = 11 index = 21
active count = 11 index = 22
active count = 11 index = 23
active count = 11 index = 24
active count = 11 index = 25
active count = 11 index = 26
active count = 11 index = 27
active count = 11 index = 28
active count = 11 index = 29
active count = 11 index = 30
active count = 11 index = 31
active count = 11 index = 32
active count = 11 index = 33
active count = 11 index = 34
active count = 11 index = 35
active count = 11 index = 36
active count = 11 index = 37
active count = 11 index = 38
active count = 11 index = 39
active count = 11 index = 40
active count = 11 index = 41
active count = 11 index = 42
active count = 11 index = 43
active count = 11 index = 44
active count = 11 index = 45
active count = 11 index = 46
active count = 11 index = 47
active count = 11 index = 48
active count = 10 index = 49
從列印訊息來看開始線程數在增加,後來穩定,可以修改休眠時間,休眠時間越短建立的線程數就越多,因為前面的還沒執行完,線程池中沒有可以執行的就需要建立;如果把休眠時間加大,建立的線程數就會少
2.newFixedThreadPool 根據傳入的參數建立線程數目
/** * 定長線程池 */public static void Function2() {ExecutorService executorService = Executors.newFixedThreadPool(3);for (int i = 0; i < 30; i++) {final int index = i;executorService.execute(new Runnable() {@Overridepublic void run() {try {System.out.println("index = " + index+ " thread count = " + Thread.activeCount());Thread.sleep(2000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}});}}
3.newScheduledThreadPool
/** * 定長線程池,可做延時 */public static void Function3() {ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);executorService.schedule(new Runnable() {@Overridepublic void run() {System.out.println("delay 3 seconds" + " thread count = "+ Thread.activeCount());}}, 3, TimeUnit.SECONDS);}/** * 定期執行,可以用來做定時器 */public static void Function4() {ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3);executorService.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {System.out.println("delay 1 seconds, and excute every 3 seconds"+ " thread count = " + Thread.activeCount());}}, 1, 3, TimeUnit.SECONDS);}
列印結果
delay 1 seconds, and excute every 3 seconds thread count = 2delay 1 seconds, and excute every 3 seconds thread count = 3delay 1 seconds, and excute every 3 seconds thread count = 4delay 1 seconds, and excute every 3 seconds thread count = 4delay 1 seconds, and excute every 3 seconds thread count = 4delay 1 seconds, and excute every 3 seconds thread count = 4delay 1 seconds, and excute every 3 seconds thread count = 4delay 1 seconds, and excute every 3 seconds thread count = 4delay 1 seconds, and excute every 3 seconds thread count = 4
4.newSingleThreadExecutor這個最簡單
/** * 單例線程 */public static void Function5() {ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();for (int i = 0; i < 5; i++) {final int index = i;singleThreadExecutor.execute(new Runnable() {@Overridepublic void run() {try {System.out.println("index = " + index+ " thread count = " + Thread.activeCount());Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}});}}
列印結果:
index = 0 thread count = 2index = 1 thread count = 2index = 2 thread count = 2index = 3 thread count = 2index = 4 thread count = 2
只建立了一個線程