日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

五种线程池的对比与使用

發布時間:2023/12/10 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 五种线程池的对比与使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天對五種常見的java內置線程池進行講解。

線程使用的demo

public static void cache() {ExecutorService pool = Executors.newCachedThreadPool();long start = System.currentTimeMillis();pool.execute(() -> {int sum = 0;for (int i = 0; i < 10; i++) {sum = (int) Math.sqrt(i * i - 1 + i);System.out.println(sum);}});System.out.println("cache: " + (System.currentTimeMillis() - start));}

newCachedThreadPool

  • 重用之前的線程
  • 適合執行許多短期異步任務的程序。
  • 調用 execute() 將重用以前構造的線程
  • 如果沒有可用的線程,則創建一個新線程并添加到池中
  • 默認為60s未使用就被終止和移除
  • 長期閑置的池將會不消耗任何資源

源碼:

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

通過源碼可以看出底層調用的是ThreadPoolExecutor方法,傳入一個同步的阻塞隊列實現緩存。

下面說一下ThreadPoolExecutor

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

通過源碼可以看出,我們可以傳入線程池的核心線程數(最小線程數),最大線程數量,保持時間,時間單位,阻塞隊列這些參數,最大線程數設置為jvm可用的cpu數量為最佳實踐

newWorkStealingPool

  • 獲取當前可用的線程數量進行創建作為并行級別
  • 使用ForkJoinPool

源碼:

public static ExecutorService newWorkStealingPool() {return new ForkJoinPool(Runtime.getRuntime().availableProcessors(),ForkJoinPool.defaultForkJoinWorkerThreadFactory,null, true);}

通過源碼可以看出底層調用的是ForkJoinPool線程池

下面說一下ForkJoinPool

public ForkJoinPool(int parallelism,ForkJoinWorkerThreadFactory factory,UncaughtExceptionHandler handler,boolean asyncMode) {this(checkParallelism(parallelism),checkFactory(factory),handler,asyncMode ? FIFO_QUEUE : LIFO_QUEUE,"ForkJoinPool-" + nextPoolId() + "-worker-");checkPermission();}

使用一個無限隊列來保存需要執行的任務,可以傳入線程的數量,不傳入,則默認使用當前計算機中可用的cpu數量,使用分治法來解決問題,使用fork()和join()來進行調用

newSingleThreadExecutor

  • 在任何情況下都不會有超過一個任務處于活動狀態
  • 與newFixedThreadPool(1)不同是不能重新配置加入線程,使用FinalizableDelegatedExecutorService進行包裝
  • 能保證執行順序,先提交的先執行。
  • 當線程執行中出現異常,去創建一個新的線程替換之
    源碼:
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));}

newFixedThreadPool

  • 創建重用固定數量線程的線程池,不能隨時新建線程
  • 當所有線程都處于活動狀態時,如果提交了其他任務,
    他們將在隊列中等待一個線程可用
  • 線程會一直存在,直到調用shutdown

源碼:

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

newScheduledThreadPool

  • 設定延遲時間,定期執行
  • 空閑線程會進行保留

源碼:

return new ScheduledThreadPoolExecutor(corePoolSize);

通過源碼可以看出底層調用的是一個ScheduledThreadPoolExecutor,然后傳入線程數量

下面來介紹一下ScheduledThreadPoolExecutor

public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());}

通過源碼可以看出底層調用了ThreadPoolExecutor,維護了一個延遲隊列,可以傳入線程數量,傳入延時的時間等參數,下面給出一個demo

public static void main(String[] args) {ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);for (int i = 0; i < 15; i = i + 5) {pool.schedule(() -> System.out.println("我被執行了,當前時間" + new Date()), i, TimeUnit.SECONDS);}pool.shutdown();}

執行結果

我被執行了,當前時間Fri Jan 12 11:20:41 CST 2018 我被執行了,當前時間Fri Jan 12 11:20:46 CST 2018 我被執行了,當前時間Fri Jan 12 11:20:51 CST 2018

有的小伙伴可能會用疑問,為什么使用schedule()而不使用submit()或者execute()呢,下面通過源碼來分析

public void execute(Runnable command) {schedule(command, 0, NANOSECONDS);}public Future<?> submit(Runnable task) {return schedule(task, 0, NANOSECONDS);}

通過源碼可以發現這兩個方法都是調用的schedule(),而且將延時時間設置為了0,所以想要實現延時操作,需要直接調用schedule()

下面我們再來分析一下submit()和execute()的以及shutdown()和shutdownNow()的區別

  • submit(),提交一個線程任務,可以接受回調函數的返回值嗎,適用于需要處理返回著或者異常的業務場景
  • execute(),執行一個任務,沒有返回值
  • shutdown(),表示不再接受新任務,但不會強行終止已經提交或者正在執行中的任務
  • shutdownNow(),對于尚未執行的任務全部取消,正在執行的任務全部發出interrupt(),停止執行

五種線程池的適應場景

  • newCachedThreadPool:用來創建一個可以無限擴大的線程池,適用于服務器負載較輕,執行很多短期異步任務。
  • newFixedThreadPool:創建一個固定大小的線程池,因為采用無界的阻塞隊列,所以實際線程數量永遠不會變化,適用于可以預測線程數量的業務中,或者服務器負載較重,對當前線程數量進行限制。
  • newSingleThreadExecutor:創建一個單線程的線程池,適用于需要保證順序執行各個任務,并且在任意時間點,不會有多個線程是活動的場景。
  • newScheduledThreadPool:可以延時啟動,定時啟動的線程池,適用于需要多個后臺線程執行周期任務的場景。
  • newWorkStealingPool:創建一個擁有多個任務隊列的線程池,可以減少連接數,創建當前可用cpu數量的線程來并行執行,適用于大耗時的操作,可以并行來執行
  • ?

    轉自:https://www.jianshu.com/p/135c89001b61

    總結

    以上是生活随笔為你收集整理的五种线程池的对比与使用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。