對於Java線程池的學習

爲什麼要使用線程池?

  1. 一個線程的執行過程包括:創建、執行、銷燬 三個階段。我們最關注的是線程執行階段。創建、銷燬線程伴隨着系統資源的開銷。線程池緩存線程,可以用已有的閒置線程來執行新任務,避免線程創建、銷燬過程帶來的系統開銷。
  2. 若線程併發數量過多,搶佔系統資源會導致阻塞。線程池能有效的控制西安城最大的併發數。
  3. 對於線程進行一些簡單的管理策略。如延遲執行、定時循環執行等策略。

1 爲什麼要用線程池?

      線程池提供了一種限制和管理資源(包括執行一個任務)。 每個線程池還維護一些基本統計信息,例如已完成任務
的數量。
       這裏借用《Java併發編程的藝術》提到的來說一下使用線程池的好處:

  • 降低資源消耗。 通過重複利用已創建的線程降低線程創建和銷燬造成的消耗。
  • 提高響應速度。 當任務到達時,任務可以不需要的等到線程創建就能立即執行。
  • 提高線程的可管理性。 線程是稀缺資源,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配,調優和監控。

2 實現Runnable接口和Callable接口的區別

       如果想讓線程池執行任務的話需要實現的Runnable接口或Callable接口。 Runnable接口或Callable接口實現類都可
以被ThreadPoolExecutor或ScheduledThreadPoolExecutor執行。兩者的區別在於 Runnable 接口不會返回結果但
是 Callable 接口可以返回結果

3 執行execute()方法和submit()方法的區別是什麼呢?

  • 1) execute() 方法用於提交不需要返回值的任務,所以無法判斷任務是否被線程池執行成功與否;
  • 2)submit()方法用於提交需要返回值的任務。線程池會返回一個future類型的對象,通過這個future對象可以判斷任務是否執行成功,並且可以通過future的get()方法來獲取返回值,get()方法會阻塞當前線程直到任務完成,而使用get(long timeout,TimeUnit unit) 方法則會阻塞當前線程一段時間後立即返回,這時候有可能任務沒有執行完。

4 如何創建線程池(4種線程池的區別)

Java 裏面線程池的頂級接口是Executor,但是嚴格意義上講Executor 並不是一個線程池,而只是一個執行線程的工具。真正的線程池接口是ExecutorService。

Java通過Executors提供四種線程池,分別爲:

  • newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。
  • newFixedThreadPool 創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
  • newScheduledThreadPool 創建一個定長線程池,支持定時及週期性任務執行。
  • newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。

《阿里巴巴Java開發手冊》中強制線程池不允許使用 Executors 去創建,而是通過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同學更加明確線程池的運行規則,規避資源耗盡的風險。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章