5.ExecutorServie線程池
通過Executors的靜態(tài)方法來創(chuàng)建,一般有三種:
1.單線程 :Executors.newSingleThreadExecutor();
2.固定數(shù)量線程 :Executors.newFixedThreadPool();
3.動(dòng)態(tài)線程 :Executors.newCachedThreadPool();
這里我們用固定5個(gè)線程來應(yīng)用,使用方法是創(chuàng)建ExecutorService對象,然后執(zhí)行submit(r)可以發(fā)起一個(gè)Runnable對象。用線程池來管理的好處是,可以保證系統(tǒng)穩(wěn)定運(yùn)行,適用與有大量線程,高工作量的情景下使用,假如要展示1000張圖片如果創(chuàng)建1000個(gè)線程去加載,保證系統(tǒng)會死掉。用線程池就可以避免這個(gè)問題,可以用5個(gè)線程輪流執(zhí)行,5個(gè)一組,執(zhí)行完的線程不直接回收而是等待下次執(zhí)行,這樣對系統(tǒng)的開銷就可以減小不少。
private void loadImagesByExecutors(final String url,final int id){
service.submit(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
Log.e("當(dāng)前線程:", ""+Thread.currentThread().getName());
try {
final Drawable drawable = Drawable.createFromStream(new URL(url).openStream(), "image.gif");
mainHandler.post(new Runnable(){
@Override
public void run() {//這將在主線程運(yùn)行
// TODO Auto-generated method stub
((ImageView)MainActivity.this.findViewById(id)).setImageDrawable(drawable);
}
});
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
Log:
其實(shí)可能沒有說清楚,第一種不算多線程。
1.loadImagesByHandler()是通過Handler.post()方法,構(gòu)建兩個(gè)Handler進(jìn)行通信。
2.loadImagesByThread(),這個(gè)是直接new Thread()發(fā)起線程,在主線程的handler處理消息
3.loadImageByAsyncTask(),這個(gè)用的是異步任務(wù),所有實(shí)現(xiàn)在它的內(nèi)部結(jié)構(gòu)里,可以在里頭操作Ui.
4.loadImagesByExecutors()用的是線程池,使得線程可控,保證穩(wěn)定運(yùn)行。
其實(shí)常用的就是后三種,第二個(gè)用法靈活,簡單,但不適宜大數(shù)量任務(wù);第三個(gè)一般適用于單個(gè)任務(wù),一次性任務(wù);第四個(gè)一般用于大數(shù)量,高密度執(zhí)行的使用情景,比如批量加載圖片,批量下載文件等。
看一眼圖吧: