java 線程池ThreadPoolExecutor 如何與 AsyncTask() 組合使用。


轉載請聲明出處謝謝!http://www.cnblogs.com/linguanh/

 

這里主要使用Executors中的4種靜態創建線程池實例方法中的 newFixedThreadPool()來舉例講解。

簡單說下Executors類,提供的一系列創建線程池的方法:

他們都有兩個構造方法

1. --------newFixedThreadPool

(創建一個定長線程池,可控制線程最大並發數,超出的線程會在隊列中等待。)

public static ExecutorService newFixedThreadPool(int nThreads);
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);

2. --------newSingleThreadExecutor

(創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。)

public static ExecutorService newSingleThreadExecutor();
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory);

3. --------newCachedThreadPool

(創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程)
public static ExecutorService newCachedThreadPool();
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory);

4. --------newScheduledThreadPool

創建一個定長線程池,支持定時及周期性任務執行。)

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);

*******************************************

定長線程池-newFixedThreadPool 的第一個構造方法

public static ExecutorService newFixedThreadPool(int nThreads);傳入的參數nThreads是最大的同時進行、並發的線程數。如果我定義它是3,那么同時執行3個,超過的了就要排隊等待,流水線操作形式。

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);

這個構造函數的第一個參數和上面的一個樣,第二個是線程工廠,它的作用:

文檔中是這樣說的

這是什么意思呢? 其實就是說,在把線程加入線程池之前,都對它們共同進行一些操作,例如改變一些屬性。比如說setName(),thread-1和2、3、4 依次通過一個for 循環加入到線程池 中,他們的 Name 都會被改變。

 

線程池一般的使用方法:

通過 Executors.newFixedThreadPool(...).execute(Runnable()) 並發運行,例如下面的代碼片段

 

 1 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
 2 for (int i = 0; i < 10; i++) {
 3     final int index = i;
 4     fixedThreadPool.execute(new Runnable() {
 5  
 6         @Override
 7         public void run() {
 8             try {
 9                 Log.d("******", Thread.currentThread().getId() + "  thread name: " + Thread.currentThread().getName()+"--"+index);
10                 Thread.sleep(2000);
11             } catch (InterruptedException e) {
12                 // TODO Auto-generated catch block
13                 e.printStackTrace();
14             }
15         }
16     });
17 }

 

運行結果如下

因為線程池大小為3,最多3個同時運行,每個輸出index后sleep 2秒,所以每兩秒打印3個數字。

 

線程池和AsyncTask()結合使用:

 

AsyncTask() 知識惡補入口:http://www.2cto.com/kf/201203/122729.html

這里只說下 AsyncTask()的executeOnExecutor() 方法,是3.0后新增的一個方法。executeOnExecutor(Executor exec, Object... params),

 

該方法接受2個參數:

第一個參數是Executor,即是我們的線程池實例,默認的可以傳入AsyncTask.THREAD_POOL_EXECUTOR,多線程並發,我們上面的是自定義的線程池,默認的最大並發5個,隊列最大128個,當然,我們可以new 一個ThreadPoolExecutor 實例,通過傳入參數改變這些限制;

第二個是任務參數。即是AsyncTask()中的第一個參數,我們可以在doInBackground()中獲取它,我下面的例子中,這個參數是字符串。

 

 

 

 

下面通過運行代碼看看它和 AsyncTask() 是怎樣聯系的

 

  1 package cn.mr.ams.threadpool;
  2 
  3 import android.app.Activity;
  4 import android.os.AsyncTask;
  5 import android.os.Bundle;
  6 import android.util.Log;
  7 import android.view.Menu;
  8 import android.view.MenuItem;
  9 
 10 import java.util.concurrent.CyclicBarrier;
 11 import java.util.concurrent.ExecutorService;
 12 import java.util.concurrent.Executors;
 13 import java.util.concurrent.ThreadFactory;
 14 
 15 
 16 public class MyActivity extends Activity {
 17 
 18     CyclicBarrier barrier = new CyclicBarrier(3);
 19     public static int j = 0 ;
 20     public final Object myTPLock = new Object();//對象鎖,主要用來實現同步,我這里並沒有使用
 21     public static ExecutorService myTP = null;//和 AsyncTask() 連用
 22     public static ExecutorService myTP_1 = Executors.newFixedThreadPool(3);//第一種構造函數
 23     //private List<String> test = new ArrayList<String>();
 24 
 25     private String[] test = new String[]{"a--","b--","c--","d--","e--"};
 26 
 27     @Override
 28     protected void onCreate(Bundle savedInstanceState) {
 29         super.onCreate(savedInstanceState);
 30         setContentView(R.layout.activity_my);
 31         //采用 第二種 構造方法,改寫下 線程工廠 對象,使每次加入線程池中的線程都能被設置定義的屬性
 32         myTP = Executors.newFixedThreadPool(3, new ThreadFactory() {
 33             @Override
 34             public Thread newThread(Runnable r) {
 35                 Thread t = new Thread(r);
 36                 //我把所加入到改線程池的線程全改名了
 37                 t.setName("LinGuanHong");
 38                 // 設置線程的優先級別
 39                 t.setPriority(Thread.NORM_PRIORITY - 1);
 40                 return t;
 41             }
 42         });
 43         for(String item : test) {
 44             //通過 for 循環,把 AsyncTask() 異步線程逐個 加入到線程池中
 45             new myThread(barrier).executeOnExecutor(myTP,item);
 46             //SystemClock.sleep(10);//能起到一定的延時,實現按順序進行
 47         }
 48         /*for (int i = 0; i < 10; i++) {
 49             final int index = i;
 50             myTP_1.execute(new Runnable() {
 51                 @Override
 52                 public void run() {
 53                     try {
 54                         Log.d("******", Thread.currentThread().getId() + "  thread name: " + Thread.currentThread().getName()+"--"+index);
 55                         Thread.sleep(2000);
 56                     } catch (InterruptedException e) {
 57                         // TODO Auto-generated catch block
 58                         e.printStackTrace();
 59                     }
 60                 }
 61             });
 62         }*/
 63 
 64     }
 65 
 66 
 67 public class myThread extends AsyncTask<Object, Void, String> {
 68     private CyclicBarrier barrier = null;
 69     public myThread(CyclicBarrier barrier){
 70         this.barrier = barrier;
 71     }
 72 
 73     @Override
 74     protected String doInBackground(Object[] params) {
 75         Object id = params[0];
 76         String idString = id.toString();
 77         //synchronized (myTPLock) {
 78         Log.d("******", idString + " id: " + Thread.currentThread().getId() + "  " +
 79                 "thread name: " + Thread.currentThread().getName()+" "+MyActivity.j);
 80         //}
 81         MyActivity.j++;
 82         return null;
 83     }
 84 }
 85 
 86 
 87     @Override
 88     public boolean onCreateOptionsMenu(Menu menu) {
 89         // Inflate the menu; this adds items to the action bar if it is present.
 90         getMenuInflater().inflate(R.menu.my, menu);
 91         return true;
 92     }
 93 
 94     @Override
 95     public boolean onOptionsItemSelected(MenuItem item) {
 96         // Handle action bar item clicks here. The action bar will
 97         // automatically handle clicks on the Home/Up button, so long
 98         // as you specify a parent activity in AndroidManifest.xml.
 99         int id = item.getItemId();
100         if (id == R.id.action_settings) {
101             return true;
102         }
103         return super.onOptionsItemSelected(item);
104     }
105 }

 

 

 

運行結果

在這里我們可以驗證,我們采用第二種構造方法,在線程工廠中改變 各線程的名字。

在我的代碼45行中,我通過for 循環有順序地傳入 a~e 字符串,但是這里的線程並沒有按照順序運行。即是並發了,因為AsyncTask本身是異步線程,我們再看上述代碼19行,我設置了個靜態的 int 標記,在 AsyncTask() 里面 78~81行沒打一次 log 就++,按照我們對異步、並發線程的理解,和可能就會出現,輸出的0~5是不按照順序的,但是上面是按照順序的,不僅僅是一次的截圖,我自己測試過很多次,0~5的輸出都是按順序的。

 

我自己的總結,可能不一定對,有錯請大家指出:

把AsyncTask()異步線程加入到線程池中運行,能夠很高效地提高執行任務的速度,如果不加其他操作限制,每個線程的執行可能是不按照順序的,但是,他們卻沒有出現搶占資源的狀況??

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM