1. 程式人生 > >java執行緒池(ThreadPoolExecutor)原始碼解析一

java執行緒池(ThreadPoolExecutor)原始碼解析一

執行緒池使用如下

 public static void main(String[] args) {
      int coreSize = 1;//核心執行緒數
      int maxSize = 2;//最大執行緒數
      long keepAliveTime = 10;//臨時執行緒空閒時間
      TimeUnit unit = TimeUnit.MINUTES;//臨時執行緒空閒時間單位
      BlockingQueue<Runnable> blockQueue = new LinkedBlockingQueue<Runnable>();//用於存任務的阻塞佇列
RejectedExecutionHandler handler = new RejectedExecutionHandler() {//任務佇列滿了以後對不能入隊的任務的處理策略 @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { System.out.println("執行緒池已滿"); } }; ThreadPoolExecutor executor = new
ThreadPoolExecutor(coreSize, maxSize, keepAliveTime, unit, blockQueue, handler); for (int i = 0; i < 10; i++) { executor.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread()); } }); } executor.shutdown(); }

excecute()方法

可以看出核心方法是execute() 方法,下面是加了註釋的execute()方法

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * 
         * 1. 如果執行緒數小於核心執行緒數,則啟動一個新的執行緒,並將傳入的runable作為他的第一個任務。
         * addWorker()方法自動檢查執行緒池執行狀態和工作執行緒數,如果當前狀態不應該再啟動新的執行緒,
         * addwoker()返回false
         * 
         * 2.  如果一個task成功進入佇列,還是要再檢查一次是否需要建立一個新的執行緒(因為在上一次檢查後,
         * 之前存活的執行緒的生命週期可能已經結束了),或者進入這個方法之後執行緒池被關閉了。因此重新檢查狀態,
         * 根據情況來決定是移除任務還是再建立一個執行緒
         *
         * 3. 如果不能將任務放入佇列,就嘗試再啟動一個新的執行緒。如果失敗了,那就說明執行緒池關閉了或者執行緒池滿了,
         * 所以後面執行拒絕策略
         */
        int c = ctl.get(); //ctl 是一個 AtomicInteger,用來存執行緒池的狀態和工作執行緒數量,以後會說明
        if (workerCountOf(c) < corePoolSize) { //workerCountOf(c) 方法獲取執行緒池已有執行緒數量
            if (addWorker(command, true)) //addWoker方法嘗試建立新的執行緒執行任務
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            /*下面又進行了一次檢查,主要是防止這種情況:執行緒A執行完上面的isRunning,返回執行中,然後掛起。
            * 這時候執行緒B呼叫了shutdown,關閉了執行緒池,這時候如果成功將執行緒池內所有執行緒結束了,這是執行緒A繼續執行
            * workQueue.offer(command) 將任務入隊,如果沒有下面的第二次檢查,這個任務將漏掉,既沒有執行run方法,
            * 也沒有執行拒絕策略
            */
            if (! isRunning(recheck) && remove(command))//isRunning(recheck) 返回當前執行緒的狀態是否是執行中
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command); //reject方法很簡單就是呼叫了傳入的 rejectExcetpionHandler
    }

reject(command)方法

    /**
     * Invokes the rejected execution handler for the given command.
     * Package-protected for use by ScheduledThreadPoolExecutor.
     */
    final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }