Executor

Executors

Executors爲Executor,ExecutorService,ScheduledExecutorService,ThreadFactory和Callable類提供了一些工具方法,類似於集合中的Collections類的功能

  • newCachedThreadPool
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

功能:它將會爲每個任務創建一個線程,此線程池的最大值是Integer的最大值(2^31-1),60秒內可以重用已經創建的線程,如果線程池的大小超過了處理任務所需要的線程,那麼就會回收部分空閒的線程
適用:該線程池比較適合沒有固定大小並且比較快速就能完成的小任務

  • newFixedThreadPool
  public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

功能:創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,再提交新任務,任務將會進入等待隊列中等待。如果某個線程因爲執行異常而結束,那麼線程池會補充一個新線程

  • newSingleThreadExecutor
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

功能:創建一個單線程的線程池。也就是相當於單線程串行執行所有任務。如果這個唯一的線程因爲異常結束,那麼會有一個新的線程來替代,。此線程池保證所有任務的執行順序按照任務的提交順序執行

除了CachedThreadPool使用的是直接提交策略的緩衝隊列以外,其餘兩個採用的都是無界緩衝隊列

以上三種都使用ThreadPoolExecutor創建

  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

 private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

corePoolSize:核心線程數量,小於corePoolSize都會直接創建線程
maximumPoolSize:最大線程數量,大於最大線程數量則由拒絕策略處理
keepAliveTime:線程最大空閒存活時間
unit:線程最大空閒存活時間單位
workQueue:緩衝隊列,超過任務超過corePoolSize大小後,放入workQueue隊列進行緩衝處理
threadFactory:線程工廠
defaultHandler:拒絕處理程序策略 默認AbortPolicy 拋出異常

拒絕處理程序策略

  • 默認的ThreadPoolExecutor.AbortPolicy

    處理程序遭到拒絕將拋出運行時RejectedExecutionException;

public static class AbortPolicy implements RejectedExecutionHandler {
        public AbortPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }
  • ThreadPoolExecutor.CallerRunsPolicy

    調用excute任務本身的線程處理,主線程直接調用,如果執行程序已關閉,則會丟棄該任務

public static class CallerRunsPolicy implements RejectedExecutionHandler {
        public CallerRunsPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
  • ThreadPoolExecutor.DiscardPolicy

    不能執行的任務將被刪除;

  public static class DiscardPolicy implements RejectedExecutionHandler {
        public DiscardPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }
  • ThreadPoolExecutor.DiscardOldestPolicy

    如果執行程序尚未關閉,則位於工作隊列頭部的任務將被刪除,然後重試執行程序(如果再次失敗,則重複此過程)。

 public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        public DiscardOldestPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }

ThreadFactory

默認同一個 ThreadGroup 中一律使用 Executors.defaultThreadFactory() 創建線程,並且這些線程具有相同的 NORM_PRIORITY 優先級和非守護進程狀態。通過提供不同的 ThreadFactory,可以改變線程的名稱、線程組、優先級、守護進程狀態等等。

 private static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

ExecutorService執行方法:

  • execute(Runnable)
    這個方法接收一個Runnable實例,並且異步的執行,無法知道結果
  • submit(Runnable)
    這個方法接收一個Runnable實例,並且異步的執行,返回一個Future對象,可以檢查結果
Future future = executorService.submit(new MyRunnable);
//方法會阻塞,返回null表示執行成功
future.get(); 
  • submit(Callable)
    也會返回一個Future對象,但是除此之外,submit(Callable)接收的是一個Callable的實現,Callable接口中的call()方法有一個返回值,可以返回任務的執行結果
Future future = executorService.submit(new MyCallable());
//方法會阻塞,返回值爲Call()
future.get(); 

當我們使用完成ExecutorService之後應該關閉它,否則它裏面的線程會一直處於運行狀態。
舉個例子,如果的應用程序是通過main()方法啓動的,在這個main()退出之後,如果應用程序中的ExecutorService沒有關閉,這個應用將一直運行。之所以會出現這種情況,是因爲ExecutorService中運行的線程會阻止JVM關閉。
調用shutdown()方法之後,ExecutorService不會立即關閉,但是它不再接收新的任務,直到當前所有線程執行完成纔會關閉。
調用shutdownNow()方法。這個動作將跳過所有正在執行的任務和被提交還沒有執行的任務。但是它並不對正在執行的任務做任何保證,有可能它們都會停止,也有可能執行完成。

ScheduledExecutorService

定時任務線程池

  • schedule (Runnable task, long delay, TimeUnit timeunit)
    指定延遲之後運行task。這個方法有個問題,就是沒有辦法獲知task的執行結果。如果我們想獲得task的執行結果,我們可以傳入一個Callable的實例
  • schedule (Callable task, long delay, TimeUnit timeunit)
    這個方法與schedule (Runnable task)類似,也是在指定延遲之後運行task,不過它接收的是一個Callable實例,此方法會返回一個ScheduleFuture對象,通過ScheduleFuture我們可以取消一個未執行的task,也可以獲得這個task的執行結果
  • scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)
    週期性的調度task執行。task第一次執行的延遲根據initialDelay參數確定,以後每一次執行都間隔period時長。
    如果task的執行時間大於定義的period,那麼下一個線程將在當前線程完成之後再執行。整個調度保證不會出現一個以上任務同時執行
  • scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit)
    與scheduleAtFixedRate類似,scheduleWithFixedDelay中,period指的當前任務的結束執行時間到下個任務的開始執行時間。
發佈了15 篇原創文章 · 獲贊 5 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章