阿裏推薦的線程使用方法 ThreadPoolExecutor
先說一下關於線程的概念
任務:線程需要執行的代碼,也就是Runnable
任務隊列:線程滿了,就任務就放入任務隊列裏等待,等其他任務在線程裏執行完,這個線程就空出來了,任務隊列就將最早來的未執行的任務放入線程執行。
核心線程:線程池一直存在的線程
最大線程數量:指的是線程池所容納的最多的線程數量
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
第一個是核心線程數量,第二個是最大線程數量,第三個是非核心線程的閑置超時時間,超過這個時間就會被回收,第四個是線程池中的任務隊列模式。
我們主要講這個任務隊列模式
1.LinkedBlockingDeque
我先上一個例子代碼,再來嘮嗑
public class MainActivity extends AppCompatActivity {
Button button; ThreadPoolExecutor executor; Runnable myRunnable = new Runnable() { @Override public void run() { try { Thread.sleep(2000); System.out.println(Thread.currentThread().getName() + " run"); } catch (InterruptedException e) { e.printStackTrace(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.btn_record_video); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { executor.execute(myRunnable); executor.execute(myRunnable); executor.execute(myRunnable); } }); executor = new ThreadPoolExecutor(3, 6, 3, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>()); }
}
當我們點擊一次按鈕
03-03 15:00:43.503 5292-5333/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:00:43.505 5292-5335/com.example.zth.seven I/System.out: pool-1-thread-3 run
03-03 15:00:43.505 5292-5334/com.example.zth.seven I/System.out: pool-1-thread-2 run
連續點擊兩次
03-03 15:10:47.941 7114-7259/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:10:47.942 7114-7261/com.example.zth.seven I/System.out: pool-1-thread-3 run
03-03 15:10:49.942 7114-7260/com.example.zth.seven I/System.out: pool-1-thread-2 run
03-03 15:10:49.942 7114-7259/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:10:49.942 7114-7261/com.example.zth.seven I/System.out: pool-1-thread-3 run
這個時候就可以看出雖然說是最大線程數量是6,但是只用核心線程,不創建新線程,如果核心線程用完了就在隊列裏等待,隊列的大小沒有限制(你可隨便點,他反正後來都會執行)
但是還沒完這個LinkedBlockingDeque還可以設置隊列數量,如果我把隊列設置為2
executor = new ThreadPoolExecutor(3, 6, 3,
TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(2));
然後連續點擊2兩次
03-03 15:19:39.851 8971-9013/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:19:39.851 8971-9014/com.example.zth.seven I/System.out: pool-1-thread-2 run
03-03 15:19:39.851 8971-9015/com.example.zth.seven I/System.out: pool-1-thread-3 run
03-03 15:19:40.045 8971-9016/com.example.zth.seven I/System.out: pool-1-thread-4 run
03-03 15:19:41.851 8971-9013/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:19:41.851 8971-9015/com.example.zth.seven I/System.out: pool-1-thread-3 run
他這個時候能夠創建四個線程了,為何,首先第一次點擊占了三個核心線程,然後第二次點擊將前兩次任務放入隊列裏,然後隊列滿了就創建一個新線程用來執行最後一個任務
如果我們連續點擊三次,程序在我們點擊第三次就崩潰了,因為線程數量超出最大線程數量了
總結:LinkedBlockingDeque就首先使用核心線程,核心線程用完了就把任務放入隊列裏等待,如果隊列滿了就創建新線程,註意不設置隊列數量,他就默認無限大。
2.SynchronousQueue
我們還是和以前一樣換掉一行代碼
executor = new ThreadPoolExecutor(3, 6, 3,
TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
點擊一次
03-03 15:39:31.915 12403-12446/com.example.zth.seven I/System.out: pool-1-thread-2 run
03-03 15:39:31.915 12403-12447/com.example.zth.seven I/System.out: pool-1-thread-3 run
03-03 15:39:31.915 12403-12445/com.example.zth.seven I/System.out: pool-1-thread-1 run
連續點擊兩次
03-03 15:39:53.204 12403-12446/com.example.zth.seven I/System.out: pool-1-thread-2 run
03-03 15:39:53.204 12403-12445/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:39:53.204 12403-12447/com.example.zth.seven I/System.out: pool-1-thread-3 run
03-03 15:39:53.371 12403-12501/com.example.zth.seven I/System.out: pool-1-thread-5 run
03-03 15:39:53.371 12403-12502/com.example.zth.seven I/System.out: pool-1-thread-6 run
03-03 15:39:53.371 12403-12500/com.example.zth.seven I/System.out: pool-1-thread-4 run
可以看出來當核心線程占滿時他沒有將任務放入隊列裏去等待,而是直接創建新線程取執行任務
連續點擊三次
程序崩潰,因為他創建的線程超過了最大線程數量,
總結:SynchronousQueue很單純,不使用隊列,核心線程用完了就創建新線程,
參考文章:
http://blog.csdn.net/qq_25806863/article/details/71126867
阿裏推薦的線程使用方法 ThreadPoolExecutor