Java多線程基本概念

來源:互聯網
上載者:User

標籤:

基本概念

 

線程與任務的概念不一樣。

任務:通常是一些抽象的且離散的工作單元,比如在Web請求中,針對使用者的請求需要返回相應的頁面是一個任務,在Java中實現Runnable介面的類也是一個任務.

線程:執行任務的實體,可以在單個線程中串列地執行各項任務,例如單線程串列執行Web請求,也可以在為每個請求建立一個線程執行。

任務是一組邏輯工作單元,而線程則是使任務非同步執行的機制。

一個簡單的例子:當我們定義了一個Runnable對象時,即任務,使用new Thread(Runnable).start()即將任務放到實際的線程中執行。

 

Executor線程池

 

Web應用中有兩種執行任務的策略:

  • 把所有任務放在單個線程中串列執行:糟糕的響應性和輸送量。

  • 為每個任務建立一個線程並行的執行:資源管理的複雜性,體現線上程開銷大,不穩定。

所以在Java中引入了Executor(線程池)架構來簡化線程的管理工作,Executor使用Runnable作為其基本的任務表示形式,在Java類庫中,任務執行的主要抽象不是Thread,而是Executor

Executor基於生產者-消費者模式,提交任務的操作相當於生產者(產生待完成的工作單元),執行任務的線程則相當於消費者(執行完這些工作單元),這樣就將請求處理任務的提交與任務的實際執行解耦開來。在下面例子中建立一個固定長度的線程池,可以容納100個線程。

class TaskExecutionWebServer {    private static final int NTHREADS = 100;    // 調用Executors中的靜態Factory 方法可以來建立一個線程池    private static final Executor exec =                     Executors.newFixedThreadPool(NTHREADS);    public static void main(String[] args) throws IOException {        ServerSocket socket = new ServerSocket(80);        while (true) {            final Socket connection = socket.accept();            Runnable task = new Runnable() {                public void run() {                    handleRequest(connection);                }            };            // 通過execute將任務提交到工作隊列中,背景工作執行緒反覆擷取執行            exec.execute(task);        }    }}

執行策略

 

線程池是指管理一組同構背景工作執行緒的資源集區。通過重用現有的線程而不是建立新線程,可以在處理多個請求時,分攤線上程建立和銷毀過程中產生的巨大開銷。另一個額外的好處是,當請求到達時,背景工作執行緒已經存在,因為提高了響應性。

  • 工作隊列(Work Queue):線程池是與工作隊列密切相關的,其中在工作隊列中儲存了所有等待執行的任務。
  • 工作者線程(Worker Thread):從工作隊列中擷取一個任務,執行任務,然後返回線程池並等待下一個任務。

在執行策略中定義了任務執行的“What、Where、When、How”等方面,包括:

  • 該任務在哪個線程中執行
  • 任務可以按照什麼樣的順序來執行(如優先順序、FIFO、LIFO)
  • 有多少個任務可以並發執行
  • ......

 

生命週期

 

線程池生命週期(ExecutorService)

我們已經知道了如何建立一個Executor,但並沒有討論如何關閉它。為瞭解決執行服務的生命週期問題,Executor擴充了ExecutorService介面,添加了一些用於生命週期管理方法。

public interface ExecutorService extends Executor {    void shutdown();    List<Runnable> shutdownNow();    boolean isShutdown();    //...}

ExecutorService的生命週期有3種狀態:運行、關閉和已終止。shutdown()方法將執行平緩的關閉過程:不再接受新的任務,同時等待已提交任務執行完成(包括未開始執行的任務)。shutdownNow()將嘗試取消所有啟動並執行任務。關閉後再提交,由“拒絕執行處理器”處理,或者拋出RejectedExecutionException異常。

任務生命週期(Future)

由於Runnable不能返回一個值或者拋出一個受檢查的異常,存在著很大的局限性。所以引入了Callable,它認為主進入點(即call)將返回一個值,並可能拋出一個異常。

又Runnable和Callable描述都是抽象的計算任務,通常經過建立、提交、開始和完成四個階段,就如ExecutorService為Executor解決生命週期問題,Future也為一個任務解決了生命週期的問題,並提供了相應地方法來判斷是否已經完成或取消,以及擷取任務的結果和取消任務。

public interface Callable<V> {        V call() throws Exception;}public interface Future<V> {    boolean cancel(boolean mayInterruptIfRunning); // 取消任務    boolean isCancelled();    boolean isDone();    V get() throws InterruptedException, ExecutionExeception,                        CancellationExeception;    V get(long timeout, TimeUnit unit) throws                    InterruptedException, ExecutionExeception                    CancellationExeception, TimeoutException;

通過調用ExecutorService中得submit方法將返回一個Future代表該任務的生命週期,可用來獲得任務的執行結果或者取消任務。也可以顯示地為某個指定的Runnable或Callable執行個體化一個FutureTask。

在將Runnable或Callable提交到Executor的過程中,包含了一個安全發布的過程,即將Runnable或Callable從提交線程發布到最終執行任務的線程。類似地,在擷取Future結果的過程中也包含了一個安全發布,即將這個結果從計算它的線程發布到任何通過get獲得它的線程。

參考: 書本Java Concurrency in Practice

Java多線程基本概念

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.