用java編寫多執行緒程式碼的4種方法

在本文中,我們比較了幾種用Java編寫多執行緒程式碼的選項,這樣您就可以更好地判斷下一個Java專案使用哪種選項。...

多線程是一種編寫代碼以並行執行任務的方法。從Java1.0的早期開始,Java就對編寫多線程代碼提供了極好的支持。最近對Java的增強增加了在Java程序中構建多線程代碼的方式。

multi-threaded-code-java

在本文中,我們比較了其中的幾個選項,以便您可以更好地判斷下一個Java項目使用哪個選項。

Multiple worker threads within a process.

方法1:擴展線程類

Java提供了一個線程類,可以擴展該類來實現run()方法。這個run()方法是實現任務的地方。當您想在自己的線程中啟動任務時,可以創建此類的實例並調用其start()方法。這將啟動線程執行並運行到完成(或在異常中終止)。

Extending Thread allows a worker task to run in a separate thread

下面是一個簡單的Thread類,它只在指定的時間間隔內休眠,以此來模擬長時間運行的操作。

public class MyThread extends Thread{ private int sleepFor; public MyThread(int sleepFor) { this.sleepFor = sleepFor; } @Override public void run() { System.out.printf("[%s] thread starting", Thread.currentThread().toString()); try { Thread.sleep(this.sleepFor); } catch(InterruptedException ex) {} System.out.printf("[%s] thread ending", Thread.currentThread().toString()); }}

通過給線程類提供睡眠的毫秒數來創建該線程類的實例。

MyThread worker = new MyThread(sleepFor);

通過調用它的start()方法啟動這個工作線程的執行。此方法立即將控制權返回給調用方,而不等待線程終止。

worker.start();System.out.printf("[%s] main thread", Thread.currentThread().toString());

下面是運行這個代碼的輸出。它指示在工作線程執行之前打印主線程診斷。

[Thread[main,5,main]] main thread[Thread[Thread-0,5,main]] thread starting[Thread[Thread-0,5,main]] thread ending

因為在啟動工作線程之後沒有更多的語句,所以主線程在程序退出之前等待工作線程完成。這允許工作線程完成其任務。

方法2:使用具有runnable的線程實例

Java還提供了一個名為Runnable的接口,它可以由一個worker類實現,以在其run()方法中執行任務。這是創建worker類的另一種方法,而不是擴展Thread類(如上所述)。

Class Papaya extends Fruit but implements Runnable to be able to run a task in a separate thread.

下面是worker類的實現,它現在實現Runnable而不是擴展Thread。

public class MyThread2 implements Runnable { // same as above}

實現Runnable接口而不是擴展Thread類的優點是,worker類現在可以在類層次結構中擴展特定於域的類。

這是什麼意思?

例如,我們假設您有一個水果類,它實現水果的某些泛型特徵。現在您要實現一個專門處理某些水果特性的木瓜類。你可以通過讓木瓜類擴展水果類來做到這一點。

public class Fruit { // fruit specifics here}public class Papaya extends Fruit { // override behavior specific to papaya here}

現在假設您有一些Papaya需要支持的耗時任務,可以在單獨的線程中執行。這種情況可以通過讓Papaya類實現Runnable並提供執行此任務的run()方法來處理。

public class Papaya extends Fruit implements Runnable { // override behavior specific to papaya here @Override public void run() { // time c***uming task here. }}

要啟動工作線程,需要創建工作類的實例,並在創建時將其交給線程實例。當線程的start()方法被調用時,任務在一個單獨的線程中執行。

Papaya papaya = new Papaya();// set properties and invoke papaya methods here.Thread thread = new Thread(papaya);thread.start();

這是如何使用Runnable來實現在線程中執行的任務的簡要總結。

方法3:使用executorservice執行runnable

An ExecutorService provides an abstraction for creating and managing threads.

從版本1.5開始,Java提供了ExecutorService,作為在程序中創建和管理線程的新範例。它通過抽象線程的創建來概括線程執行的概念。

這是因為您可以在線程池中運行任務,就像為每個任務使用單獨的線程一樣簡單。這允許您的程序跟蹤和管理有多少線程用於輔助任務。

假設有100個輔助任務等待執行。如果您為每個worker啟動一個線程(如上所示),那麼您的程序中將有100個線程,這可能會導致程序中其他地方出現瓶頸。相反,如果使用預先分配了10個線程的線程池,那麼100個任務將由這些線程一個接一個地執行,這樣程序就不會缺少資源。此外,可以配置這些線程池線程,以便它們掛起為您執行其他任務。

ExecutorService接受可運行的任務(如上所述),並在適當的時間運行該任務。接受可運行任務的submit()方法返回一個名為Future的類的實例,該類允許調用方跟蹤任務的狀態。特別是,get()方法允許調用方等待任務完成(並提供返回代碼,如果有的話)。

在下面的示例中,我們使用靜態方法newSingleThreadExecutor()創建一個ExecutorService,正如名稱所示,它創建一個用於執行任務的線程。如果在一個任務運行時提交了多個任務,ExecutorService會將這些任務排隊等待後續執行。

我們在這裡使用的可運行實現與上面描述的相同。

ExecutorService esvc = Executors.newSingleThreadExecutor();Runnable worker = new MyThread2(sleepFor);Future<?> future = esvc.submit(worker);System.out.printf("[%s] main thread", Thread.currentThread().toString());future.get();esvc.shutdown();

請注意,當不再需要進一步提交任務時,必須正確關閉ExecutorService。

方法4:與executorservice一起使用的可調用

從版本1.5開始,Java引入了一個名為Callable的新接口。它類似於舊的Runnable接口,不同之處在於執行方法(調用call()而不是run())可以返回一個值。此外,它還可以聲明可以拋出異常。

ExecutorService還可以接受實現為可調用的任務,並使用方法在完成時返回的值返回Future。

下面是一個示例Mango類,它擴展了前面定義的Fruit類並實現了可調用接口。在call()方法中執行一項昂貴且耗時的任務。

An implementation of the Callable interface can also be used with an ExecutorService

public class Mango extends Fruit implements Callable { public Integer call() { // expensive computation here return new Integer(0); }}

下面是將類的實例提交給ExecutorService的代碼。下面的代碼還將等待任務完成並打印其返回值。

ExecutorService esvc = Executors.newSingleThreadExecutor();MyCallable worker = new MyCallable(sleepFor);Future future = esvc.submit(worker);System.out.printf("[%s] main thread", Thread.currentThread().toString());System.out.println("Task returned: " + future.get());esvc.shutdown();

你喜歡什麼?

在本文中,我們學習了一些用Java編寫多線程代碼的方法。其中包括:

  1. 擴展Thread類是最基本的,Java1.0提供了它。
  2. 如果有一個類必須擴展類層次結構中的其他類,那麼可以實現Runnable接口。
  3. 創建線程的一個更現代的工具是ExecutorService,它可以接受一個可運行實例作為要運行的任務。此方法的優點是可以使用線程池執行任務。線程池通過重用線程來幫助節約資源。
  4. 最後,還可以通過實現可調用接口並將任務提交給ExecutorService來創建任務。

你認為在你的下一個項目中你會使用這些選項中的哪一個?請在下面的評論中告訴我們。

  • 發表於 2021-03-14 04:48
  • 閱讀 ( 51 )
  • 分類:程式設計

你可能感興趣的文章

睡覺(sleep)和在java中等待(wait in java)的區別

... 關鍵區別——java中的休眠與等待 Sleep和wait是Java中用於多執行緒處理的兩種方法。sleep方法屬於Thread類,而wait方法來自Object類。Java中sleep和wait的關鍵區別在於,sleep用於在指定的毫秒數內暫停當前執行緒的執行,而wait方法用...

  • 發佈於 2020-10-19 03:04
  • 閲讀 ( 48 )

原始碼(source code)和位元組碼(bytecode)的區別

...程式可以向計算機發出指令。它是用一套特定的程式語言編寫的。程式語言有很多種。大多數程式語言都是高階程式語言。用高階語言編寫的程式很容易被人或程式設計師理解。這些程式稱為原始碼。機器無法理解它們。因此,...

  • 發佈於 2020-10-19 15:49
  • 閲讀 ( 59 )

紅寶石(ruby)和python(python)的區別

...權。Ruby有陣列、雜湊等資料型別。 rubyonrails是一個用Ruby編寫的用於web開發的web框架。它很容易嵌入到超文字標記語言(HTML)中。Ruby還可以用於構建同時執行多個執行緒的多執行緒應用程式。總的來說,Ruby對於web開發、網路程...

  • 發佈於 2020-10-19 17:41
  • 閲讀 ( 58 )

可執行(runnable)和線(thread)的區別

...現了Runnable介面。使用執行緒執行的邏輯是用run()方法編寫的。在主程式中,執行緒是透過定義一個從可執行的Demo類例項化的物件來建立的。是t1。然後,使用t1呼叫start()方法。 什麼是線(thread)? 另一種建立執行緒的方法...

  • 發佈於 2020-10-19 19:23
  • 閲讀 ( 50 )

多執行緒(multithreading)和多工處理(multitasking)的區別

關鍵區別–多執行緒與多工 多執行緒和多工看起來很相似,但它們是兩個不同的概念。計算機同時執行許多工。多執行緒和多工都與計算機效能有關。多執行緒處理和多工處理的關鍵區別在於,在多執行緒處理中,多個執行...

  • 發佈於 2020-10-20 00:38
  • 閲讀 ( 39 )

多處理(multiprocessing)和多執行緒(multithreading)的區別

關鍵區別–多處理與多執行緒 在一個計算機系統中,幾個程序同時在執行。。作業系統為程序分配資源,有必要提高CPU利用率。多處理和多執行緒處理會影響系統性能。多處理與多執行緒的關鍵區別在於,在多處理中,多個...

  • 發佈於 2020-10-20 00:55
  • 閲讀 ( 44 )

過程(process)和線(thread)的區別

...的執行緒數,有兩種型別的程序。它們是單執行緒程序和多執行緒程序。顧名思義,單執行緒程序就是隻有一個執行緒的程序。因此,這個執行緒是一個程序,只有一個活動正在發生。在多執行緒程序中,有多個執行緒,並且有...

  • 發佈於 2020-10-29 12:02
  • 閲讀 ( 46 )

初學者必備的8個eclipse鍵盤快捷鍵

本文最初是為eclipsejuno編寫的,但後來為eclipseoxygen進行了更新。 ...

  • 發佈於 2021-03-11 23:36
  • 閲讀 ( 56 )

java8lambdas簡介

... 使用lambda,可以將上述迴圈編寫為: ...

  • 發佈於 2021-03-12 08:09
  • 閲讀 ( 48 )

為什麼java虛擬機器可以幫助程式碼更好地執行

... 本機應用程式是專門為作業系統(OS)編寫的程式,也可能是為執行該作業系統的特定硬體編寫的程式。它主要是用C/C++等語言編寫的。C/C++原始碼使用編譯器編譯成物件形式,然後透過連結所需的庫將其組裝...

  • 發佈於 2021-03-13 07:13
  • 閲讀 ( 50 )
lts9441
lts9441

0 篇文章

作家榜

  1. admin 0 文章
  2. 孫小欽 0 文章
  3. JVhby0 0 文章
  4. fvpvzrr 0 文章
  5. 0sus8kksc 0 文章
  6. zsfn1903 0 文章
  7. w91395898 0 文章
  8. SuperQueen123 0 文章

相關推薦