天天看點

ThreadPoolExecutor 快速實際應用

簡要:

本教程将會告訴你,怎樣在Android上用多線程技術 同時執行 多個 耗時長 的任務。

0. 背景紹介(為什麼用ThreadPoolExecutor)

之前用的是AsyncTask,但是這個不能用于時間過長的并行任務,我是出了問題:

02-23 13:40:13.922 13922-13922/? A/DEBUG: pid: 13505, tid: 13699, name: AsyncTask #2  >>> com.example.rp.my_cv_project <<<
                                          signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x1684
                                              r0 c8756800  r1 00001680  r2 00000001  r3 9395e9f8
                                              r4 00000001  r5 12c32ac0  r6 6fe50310  r7 12c3db50
                                              r8 12c3db40  r9 dea93e00  sl 12c06688  fp 00000000
                                              ip e7cd59cc  sp bf27f3f0  lr 729176d7  pc e7de5b92  cpsr 680f0030
02-23 13:40:15.403 495-495/? E/Layer: [Application Error: com.example.rp.my_cv_project] rejecting buffer: bufWidth=1333, bufHeight=548, front.active.{w=169, h=169}
           

你跟我說,這玩意誰看得懂啊?!

PC位址也沒有,我沒辦法用add2line吧......

是以,我打算改成ThreadPoolExecutor。為什麼用這個呢?緣于官方的文檔:

To automatically run tasks as resources become available, or to allow multiple tasks to run at the same time (or both), you need to provide a managed collection of threads. To do this, use an instance of 

ThreadPoolExecutor

這裡:

Android官方教程

順便,這裡還說了,IntentService不适用于多線程同步執行的。它隻适用于單個的:

If you want to run a task repeatedly on different sets of data, but you only need one execution running at a time, an 

IntentService

 suits your needs.

好,那麼就開始用吧,我搜了一下ThreadPoolExecutor,嘩啦啦出來一堆東西,但就是沒有我想要的。

是的,你們雖然把原理講的明明白白,什麼茴香豆的四種寫法...啊不,是常用的四種線程池,但是能不能有更直接的,能讓我拿來就用的教程?

翻了半天,找到了這個部落格:參考

那我就在它基礎上,寫一個我本來想要第一眼就看到的,簡單易懂的ThreadPoolExecutor應用執行個體吧:

1. 需求

現在我想在主線程裡将十張圖檔(Bitmap)同時用多線程來進行處理。

2. 例程

首先,我們有一個負責處理圖檔的class,叫它process吧:

public class process implements Runnable, Serializable {
	Bitmap bitmap;
	int other_parameters;
	// 利用構造函數添加輸入的參數
	public process(Bitmap bitmap, int other_parameters){
		this.bitmap = bitmap;
		this.other_parameters = other_parameters;
	}
	// 處理函數,裡面利用輸入的bitmap以及other_parameters進行處理。
	public void real_process(){
		// write your own code here~~~
		// 增加一個callback來傳回主線程~
		// 具體關于callback怎麼用,請參考代碼塊下面的網站~
	}
	@Override
    public void run() {
        real_process();
    }
}
           

簡單!猴子也能學會的callback用法!它讓你可以線上程結束之後立刻獲得通知以及執行的結果,不需要用while之類的蠢法子,美滋滋。

然後,我們在主線程中,先對線程池進行一個建立:

private ThreadPoolExecutor SetThreadPoolExecuteor(){
        /*
         * Number of cores to decide the number of threads
         */
        final int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
        // 構造一個線程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(NUMBER_OF_CORES*2
                , NUMBER_OF_CORES*2, 0L,
                TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
        return threadPool;
    }
           

至于裡面的參數,我隻能說解釋已經爛大街了。我從那些部落格裡淨看這群參數的解釋了:

這個,這個,以及這個。

然後,接下來是調用:

// getBitmapArrayList,擷取bitmap的arraylist
ArrayList<Bitmap> res_split = getBitmapArrayList();
// 獲得其他參數
int other_parameters = get_other_parameters();
// 建立線程池
ThreadPoolExecutor myTPE = SetThreadPoolExecuteor();
for(int i=0;i<res_split.size();i++){
    Bitmap img = res_split.get(i);
    // 這句是開始執行~!
    myTPE.execute(new process(img,other_parameters));
}
           

恭喜!你已經完全準備好了!接下來就自己試試吧!亂七八糟的參數再根據需求調一調,美滋滋。

如果本文對你有用,我會非常開心的O(∩_∩)O~~

ThreadPoolExecutor 快速實際應用

繼續閱讀