線程池執行流程



當狀態是shutdown時,是可以添加任務爲空的現成加速隊列執行的

  • 線程池核心線程也可以超時銷燬,參數:allowCoreThreadTimeOut,默認false,時間也是keepAliveTime參數

  • 在應用入口捕獲線程池未捕獲的異常,說明:如下只能捕獲線程池調用execute方法的未捕獲的異常,submit方法的不行,submit方法的必須在執行處使用try catch手動捕獲處理,或者通過返回值調用get()方法捕獲。推薦executesubmittry catch統一思想,還有個好處是,普通線程池異常會銷燬當前線程同時創建一個新的線程,如果異常比較多創建線程也會消耗性能。

    Thread.setDefaultUncaughtExceptionHandler((thread, e) -> {
      String desc = format("捕獲DefaultUncaughtExceptionHandler異常, 線程名稱: {}", thread.getName());
      log.error(desc, e);
    });
    
  • ScheduledExecutorService拋出異常時不繼續執行時因爲下方註釋:

    public void run() {
      boolean periodic = isPeriodic();
      if (!canRunInCurrentRunState(periodic))
        cancel(false);
      else if (!periodic)
        ScheduledFutureTask.super.run();
      // 這裏執行如果拋異常會返回false,就不會不停的向隊列中反覆添加任務
      else if (ScheduledFutureTask.super.runAndReset()) {
        setNextRunTime();
        reExecutePeriodic(outerTask);
      }
    }
    
    protected boolean runAndReset() {
      if (state != NEW ||
          !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                       null, Thread.currentThread()))
        return false;
      boolean ran = false;
      int s = state;
      try {
        Callable<V> c = callable;
        if (c != null && s == NEW) {
          try {
            c.call(); // don't set result
            ran = true;
          } catch (Throwable ex) {
            setException(ex);
          }123
        }
      } finally {
        // runner must be non-null until state is settled to
        // prevent concurrent calls to run()
        runner = null;
        // state must be re-read after nulling runner to prevent
        // leaked interrupts
        s = state;
        if (s >= INTERRUPTING)
          handlePossibleCancellationInterrupt(s);
      }
      return ran && s == NEW;
    }
    
  • 普通線程池拋出異常,會銷燬當前線程,並且新建1個

        final void runWorker(Worker w) {
            Thread wt = Thread.currentThread();
            Runnable task = w.firstTask;
            w.firstTask = null;
            w.unlock(); // allow interrupts
            boolean completedAbruptly = true;
            try {
                while (task != null || (task = getTask()) != null) {
                    w.lock();
                    // If pool is stopping, ensure thread is interrupted;
                    // if not, ensure thread is not interrupted.  This
                    // requires a recheck in second case to deal with
                    // shutdownNow race while clearing interrupt
                    if ((runStateAtLeast(ctl.get(), STOP) ||
                         (Thread.interrupted() &&
                          runStateAtLeast(ctl.get(), STOP))) &&
                        !wt.isInterrupted())
                        wt.interrupt();
                    try {
                        beforeExecute(wt, task);
                        Throwable thrown = null;
                        try {
                            task.run();
                        } catch (RuntimeException x) {
                            thrown = x; throw x;
                        } catch (Error x) {
                            thrown = x; throw x;
                        } catch (Throwable x) {
                            thrown = x; throw new Error(x);
                        } finally {
                            afterExecute(task, thrown);
                        }
                    } finally {
                        task = null;
                        w.completedTasks++;
                        w.unlock();
                    }
                }
                completedAbruptly = false;
            } finally {
                processWorkerExit(w, completedAbruptly);
            }
        }
    

    拋出異常會執行processWorkerExit方法:

        private void processWorkerExit(Worker w, boolean completedAbruptly) {
            if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
                decrementWorkerCount();
    
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                completedTaskCount += w.completedTasks;
              // 移除當前worker
                workers.remove(w);
            } finally {
                mainLock.unlock();
            }
    
            tryTerminate();
    
            int c = ctl.get();
            if (runStateLessThan(c, STOP)) {
                if (!completedAbruptly) {
                    int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                    if (min == 0 && ! workQueue.isEmpty())
                        min = 1;
                    if (workerCountOf(c) >= min)
                        return; // replacement not needed
                }
              // 新建1個新的worker
                addWorker(null, false);
            }
        }
    
  • 超時銷燬邏輯

        private Runnable getTask() {
            boolean timedOut = false; // Did the last poll() time out?
    
            for (;;) {
                int c = ctl.get();
                int rs = runStateOf(c);
    
                // Check if queue empty only if necessary.
                if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                    decrementWorkerCount();
                    return null;
                }
    
                int wc = workerCountOf(c);
    
                // Are workers subject to culling?
                boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
    
              // 判斷超時,銷燬,core線程根據參數也可能被銷燬
                if ((wc > maximumPoolSize || (timed && timedOut))
                    && (wc > 1 || workQueue.isEmpty())) {
                    if (compareAndDecrementWorkerCount(c))
                        return null;
                    continue;
                }
    
                try {
                    Runnable r = timed ?
                        workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                        workQueue.take();
                    if (r != null)
                        return r;
                    timedOut = true;
                } catch (InterruptedException retry) {
                    timedOut = false;
                }
            }
        }	
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章