1. 程式人生 > >Java多執行緒-----執行緒池詳解

Java多執行緒-----執行緒池詳解

   1. 執行緒池的實現原理

      提交一個任務到執行緒池中,執行緒池的處理流程如下:

  • 判斷執行緒池裡的核心執行緒是否都在執行任務,如果不是(核心執行緒空閒或者還有核心執行緒沒有被建立)則建立一個新的工作執行緒來執行任務。如果核心執行緒都在執行任務,則進入下個流程
  • 執行緒池判斷工作佇列是否已滿,如果工作佇列沒有滿,則將新提交的任務儲存在這個工作佇列裡。如果工作佇列滿了,則進入下個流程
  • 判斷執行緒池裡的執行緒是否都處於工作狀態,如果沒有,則建立一個新的工作執行緒來執行任務。如果已經滿了,則交給飽和策略來處理這個任務

   2. 執行緒池的優點

  • 執行緒是稀缺資源,使用執行緒池可以減少建立和銷燬執行緒的次數,每個工作執行緒都可以重複使用
  • 可以根據系統的承受能力,調整執行緒池中工作執行緒的數量,防止因為消耗過多記憶體導致伺服器崩潰

   3. 執行緒的建立及使用

3.1 newCachedThreadPool() 

    建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒

這種型別的執行緒池特點是:

  • 快取型池子,先檢視池中有沒有以前建立的執行緒,如果有,就reuse,如果沒有,就建立一個新的執行緒加入池中
  •        快取型池子,通常用於執行一些生存週期很短的非同步型任務;因此一些面向連線的daemon型server中用得不多
  •        能reuse的執行緒,必須是timeout IDLE內的池中執行緒,預設timeout是60s,超過這個IDLE時長,執行緒例項將被終止及移出池
  •        注意,放入CachedThreadPool的執行緒不必擔心其結束,超過TIMEOUT不活動,其會自動被終止
package com.thread.threadpool;

import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒 * * @author yyx 2019年1月5日 */ public class CachedThreadPool { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 1; i <= 10; i++) { final int index = i; executorService.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "當前執行到:" + index); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } }); } } }

3.2 newFixedThreadPool()

    建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待

這種型別的執行緒池特點是:

  •       newFixedThreadPool與cacheThreadPool差不多,也是能reuse就用,但不能隨時建新的執行緒
  •       其獨特之處:任意時間點,最多隻能有固定數目的活動執行緒存在,此時如果有新的執行緒要建立,只能放在另外的佇列中等待,直到當前的執行緒中某個執行緒終止直接被移出池子
  •       和cacheThreadPool不同,FixedThreadPool沒有IDLE機制,所以FixedThreadPool多數針對一些很穩定很固定的正規併發執行緒,多用於伺服器       
  •       從方法的原始碼看,cache池和fixed 池呼叫的是同一個底層池,只不過引數不同:fixed池執行緒數固定,並且是0秒IDLE(無IDLE)cache池執行緒數支援0-Integer.MAX_VALUE(顯然完全沒考慮主機的資源承受能力),60秒IDLE  
package com.thread.threadpool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待
 * 
 * @author yyx 2019年1月5日
 */
public class FixedThreadPool {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        for (int i = 1; i <= 10; i++) {
            final int index = i;
            executorService.execute(new Runnable() {

                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "當前執行到:" + index);
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}

3.3 newSingleThreadExecutor()

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

這種型別的執行緒池特點是:

  • 單例執行緒,任意時間池中只能有一個執行緒
  • 用的是和cache池和fixed池相同的底層池,但執行緒數目是1-1,0秒IDLE(無IDLE)
package com.thread.threadpool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行
 * 
 * @author yyx 2019年1月5日
 */
public class SingleThreadExecutor {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 1; i <= 10; i++) {
            final int index = i;
            executorService.execute(new Runnable() {

                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "當前執行到:" + index);
                    try {
                        Thread.sleep(3000);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            });
        }
    }
}

3.4 newScheduledThreadPool()

   建立一個定長執行緒池,支援定時及週期性任務執行

這種型別的執行緒池特點是:

  • 排程型執行緒池
  • 這個池子裡的執行緒可以按schedule依次delay執行,或週期執行
package com.thread.threadpool;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 建立一個定長執行緒池,支援定時及週期性任務執行
 * 
 * @author yyx 2019年1月5日
 */
public class ScheduledThreadPool {
    public static void main(String[] args) {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
        scheduledExecutorService.schedule(new Runnable() {

            @Override
            public void run() {
                System.out.println("延遲3秒執行");
            }
        }, 3, TimeUnit.SECONDS);

        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                System.out.println("延遲3秒後每1秒執行一次");

            }
        }, 3, 1, TimeUnit.SECONDS);
    }
}