1. 程式人生 > >java多執行緒入門到理解學習筆記

java多執行緒入門到理解學習筆記

本文記錄了我個人在學習java多執行緒的時候,從入門到理解的學習過程,供同類小白進行學習參考。首先對現有的多執行緒實現方式進行總結,然後針對最佳多執行緒實現方式:執行緒池的要點進行記錄,最後記錄了在spring框架中執行緒池的實現方式。

多執行緒的實現方式

根據多執行緒的從簡到繁的實現方式,可分為三種:繼承Thread類、實現Runnable介面、使用程序池。但其中Thread類也是一個實現了Runnable介面的類,而執行緒池的實現也只是對實現了Runnable類的管理。

繼承Thread類

簡單方便,適用於簡單、獨立的應用,無法繼承現有類,不能獲取執行緒返回值,更不能對現有執行緒進行管理;

實現Runnable介面

簡單方便,可繼承現有類,不能獲取執行緒返回值,不能對現有執行緒進行管理;

程序池

即使用Executor框架,Executor框架是指java 5中引入的一系列併發庫中與executor相關的一些功能類,其中包括執行緒池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。
經典關係圖:
這裡寫圖片描述

使用執行緒池的好處:

  • 減少在建立和銷燬執行緒上所花的時間以及系統資源的開銷
  • 如不使用執行緒池,有可能造成系統建立大量執行緒而導致消耗完系統記憶體以及”過度切換”。

參考連結:

執行緒池詳解

此部分對執行緒池的元素進行進一步理解。包括:Executor,Executors,ExecutorService,CompletionService,Future,Callable,自定義執行緒池。

Executor

Executor介面中之定義了一個方法execute(Runnable command),該方法接收一個Runable例項,它用來執行一個任務,任務即一個實現了Runnable介面的類。

ExecutorService

ExecutorService介面繼承自Executor介面,它提供了更豐富的實現多執行緒的方法,比如,ExecutorService提供了關閉自己的方法,以及可為跟蹤一個或多個非同步任務執行狀況而生成 Future 的方法。 可以呼叫ExecutorService的shutdown()方法來平滑地關閉 ExecutorService,呼叫該方法後,將導致ExecutorService停止接受任何新的任務且等待已經提交的任務執行完成(已經提交的任務會分兩類:一類是已經在執行的,另一類是還沒有開始執行的),當所有已經提交的任務執行完畢後將會關閉ExecutorService。因此我們一般用該介面來實現和管理多執行緒。

ExecutorService介面提供了submit()方法,傳遞一個Callable,或Runnable,返回Future。如果Executor後臺執行緒池還沒有完成Callable的計算,這呼叫返回Future物件的get()方法,會阻塞直到計算完成。

Executors

Executors類,提供了一系列工廠方法用於創先執行緒池,返回的執行緒池都實現了ExecutorService介面。
方法包括:

  • public static ExecutorService newFixedThreadPool(int nThreads) 建立固定數目執行緒的執行緒池。應用場景:只有當這種方式會引發問題時(比如需要大量長時間面向連線的執行緒時),才需要考慮用FixedThreadPool。
  • public static ExecutorService newCachedThreadPool() 與newFixedThreadPool功能基本相同,不同之處在於不能限定最大執行緒數且自身能夠指定超時時間。建立一個可快取的執行緒池,呼叫execute 將重用以前構造的執行緒(如果執行緒可用)。如果現有執行緒沒有可用的,則建立一個新執行緒並新增到池中。終止並從快取中移除那些已有 60 秒鐘未被使用的執行緒。
  • public static ExecutorService newSingleThreadExecutor() 應用場景:建立一個單執行緒化的Executor。能新增多個執行緒,但是不能並行,沒有超時時間。
  • public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
    應用場景:建立一個支援定時及週期性的任務執行的執行緒池,多數情況下可用來替代Timer類。

一般來說,CachedTheadPool在程式執行過程中通常會建立與所需數量相同的執行緒,然後在它回收舊執行緒時停止建立新執行緒,因此它是合理的Executor的首選,只有當這種方式會引發問題時(比如需要大量長時間面向連線的執行緒時),才需要考慮用FixedThreadPool。(該段話摘自《Thinking in Java》第四版)

CompletionService

任意任務完成後就把其結果加到result中,而不用依次等待每個任務完成,可以使用CompletionService。

Future

獲取執行緒的返回結果,如果Executor後臺執行緒池還沒有完成Callable的計算,這呼叫返回Future物件的get()方法,會阻塞直到計算完成。

Callable

必須實現Callable接口才能獲取到返回結果。Runnable任務沒有返回值,而Callable任務有返回值。並且Callable的call()方法只能通過ExecutorService的submit(Callable task) 方法來執行,並且返回一個 Future,是表示任務等待完成的 Future。實現Runnable的介面也能呼叫get方法,但是結果始終為null。

自定義執行緒池

可以用ThreadPoolExecutor類建立。

spring的執行緒池

spring提供了org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor類,通過在xml檔案中配置,然後注入到需要用到執行緒池的物件例項中,即可使用。
簡單配置參考如下:

<bean id="taskExecutor"  class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">  
    <property name="corePoolSize" value="5" />  
    <property name="maxPoolSize" value="10" />  
    <property name="WaitForTasksToCompleteOnShutdown" value="true" />  
    <!--還有其他可配引數-->
</bean> 

==================================
==疑問?幫助?批評?歡迎評論 | QQ:593159978==
==================================