成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java異步編程七種實現方法,最后一種非常強大

開發 前端
異步編程是一種編程范式,旨在提高程序的響應性和性能,尤其在處理耗時操作時顯得尤為重要。它通過允許程序在等待某些操作(如I/O操作、網絡請求或數據庫查詢)完成時繼續執行其他任務,從而優化資源利用。

環境:java21

1. 簡介

異步編程是一種編程范式,旨在提高程序的響應性和性能,尤其在處理耗時操作時顯得尤為重要。它通過允許程序在等待某些操作(如I/O操作、網絡請求或數據庫查詢)完成時繼續執行其他任務,從而優化資源利用。異步編程避免了傳統同步編程中的阻塞問題,使得程序更加高效和流暢。異步編程現已成為處理并發和I/O密集型任務的重要手段。

本篇文章中我們將介紹在Java中實現異步編程的7種方法,這其中會涉及到幾個非常優秀的第三方類庫。

2. 異步編程

2.1 Thread

Thread類是Java中用于創建和管理線程的核心類。通過繼承Thread類或實現Runnable接口,可以創建新的線程。Thread類提供了線程的啟動、運行、中斷、優先級設置等方法,是實現多線程編程的基礎。

隨著Java 8中引入lambda表達式,代碼變得更加清晰和易讀,如下示例,在一個新線程中打印一個數的階乘。

public class FactorialThread extends Thread {
  private int number;
  public FactorialThread(int number, String name) {
    super(name) ;
    this.number = number;
  }
  // 計算階乘的方法
  private long factorial(int n) {
    long result = 1;
    for (int i = 1; i <= n; i++) {
      result *= i;
    }
    return result;
  }
  @Override
  public void run() {
    long result = factorial(number);
    System.out.println(Thread.currentThread().getName() + " -> " + number + " 的階乘是: " + result);
  }
  public static void main(String[] args) {
    // 創建并啟動線程,計算并打印5的階乘
    Thread t1 = new FactorialThread(5, "T1");
    t1.start();
    // 可以創建更多線程來計算其他數的階乘
    Thread t2 = new FactorialThread(7, "T2");
    t2.start();
  }
}

輸出結果

T1 -> 5 的階乘是: 120
T2 -> 7 的階乘是: 5040

我們還可以直接通過lambda計算:

Thread t3 = new Thread(() -> {
  int num = 8 ;
  int result = 1 ;
  for (int i = 1; i <= num; i++) {
    result *= i ;
  }
  System.out.println(Thread.currentThread().getName() + " -> " + num + " 的階乘是: " + result);
}, "T3") ;
t3.start() ;

通過lambda使得程序更加的簡潔易懂。

2.2 FutureTask

從Java 5起,Future接口就提供了一種通過FutureTask執行異步操作的方式。我們可以利用ExecutorService的submit方法來異步執行任務,并返回FutureTask的實例。下面通過FutureTask計算階乘。

try (ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 
    60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10))) {
  int num = 8 ;
  // 返回FutureTask實例
  Future<Integer> task = executor.submit(() -> {
    int result = 1 ;
    for (int i = 1; i <= num; i++) {
      result *= i ;
    }
    return result ;
  }) ;
  // 獲取執行結果
  Integer result = task.get() ;
  System.out.printf("%s -> %s 的階乘是: %s%n", Thread.currentThread().getName(), num, result);
  executor.shutdown() ;
}

Future還提供了isDone方法,我們可以調用該方法判斷當前是否執行完成。

if (!task.isDone()) {
  System.err.println("還未執行完成") ;
}

上面的get方法調用會將當前線程阻塞住,直到返回結果或者拋出異常。

Future<Integer> task = executor.submit(() -> {
  // ...
  System.out.println(1 / 0) ;
  return result ;
}) ;

若將程序修改為上面,如果我們沒有調用Future#get方法,那么我們將無法得知程序拋出了異常。

2.3 CompletableFuture

CompletableFuture是Java 8引入的一個類,它結合了FutureCompletionStage的特點,提供了強大的異步編程能力。通過豐富的API,它可以異步執行任務、處理結果、組合多個異步操作,并支持異常處理,極大地簡化了異步編程的復雜性。下面通過該類實現階乘計算。

final int num = 10 ;
CompletableFuture<Long> cf = CompletableFuture.supplyAsync(() -> {
  long result = 1 ;
  for (int i = 1; i <= num; i++) {
    result *= i ;
  }
  return result ;
}) ;
Long result = cf.get() ;
System.out.printf("%s -> %s 的階乘是: %s%n", Thread.currentThread().getName(), num, result);

我們不需要顯式地使用ExecutorServiceCompletableFuture內部使用ForkJoinPool來異步處理任務。因此,它使我們的代碼更加簡潔。

我們還可以通過調用join方法來等待異步線程的執行完成。

CompletableFuture.runAsync(() -> {
  System.out.printf("%s - %s 開始執行任務%n", Thread.currentThread().getName(), System.currentTimeMillis()) ;
  try {
    // 模擬耗時任務
    TimeUnit.SECONDS.sleep(2) ;
  } catch (InterruptedException e) {}
  System.out.printf("%s - %s 任務執行完成%n", Thread.currentThread().getName(), System.currentTimeMillis()) ;
}).join() ;

輸出結果

ForkJoinPool.commonPool-worker-1 - 1738806351732 開始執行任務
ForkJoinPool.commonPool-worker-1 - 1738806353742 任務執行完成

2.4 Guava

Guava提供了ListenableFuture類來執行異步操作,允許注冊回調函數以處理操作完成時的結果或異常,增強了Future的功能。

引入依賴

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>33.4.0-jre</version>
</dependency>

還是以計算階乘為例:

ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 
  60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10)) ;
ListeningExecutorService les = MoreExecutors.listeningDecorator(executor);
int num = 8 ;
ListenableFuture<Long> future = les.submit(() -> {
  long result = 1 ;
  for (int i = 1; i <= num; i++) {
    result *= i ;
  }
  return result ;
}) ;
System.out.printf("%s -> %s 的階乘是: %s%n", Thread.currentThread().getName(), num, future.get());

我們還可以通過注冊回調的機制來獲取結果

future.addListener(() -> {
  System.err.printf("%s - 計算完成%n", Thread.currentThread().getName()) ;
  try {
    System.out.printf("%s -> %s 的階乘是: %s%n", Thread.currentThread().getName(), num, future.get());
  } catch (InterruptedException | ExecutionException e) {
  }
}, executor) ;

輸出結果

pool-1-thread-2 - 計算完成
pool-1-thread-2 -> 8 的階乘是: 40320

當Future執行完成后,會自動執行注冊的監聽器,你也可以注冊多個監聽器(但是不保證執行的順序)。

2.5 EA Async

ea-async庫允許以順序方式編寫異步(非阻塞)代碼。因此,它使得異步編程變得更加容易,并且能夠自然地擴展。

引入依賴

<dependency>
  <groupId>com.ea.async</groupId>
  <artifactId>ea-async</artifactId>
  <version>1.2.3</version>
</dependency>

注:多年未更新了。

static {
  Async.init(); 
}
public static long factorial(long num) {
  long result = 1 ;
  for (int i = 1; i <= num; i++) {
    result *= i ;
  }
  return result ;
}
public static void main(String[] args) {
  final long num = 10 ;
  CompletableFuture<Long> completableFuture = CompletableFuture.supplyAsync(() -> factorial(num));
  long result = Async.await(completableFuture) ;
  System.out.printf("%s -> %s 的階乘是: %s%n", Thread.currentThread().getName(), num, result) ;
}

Async#await這個方法的行為類似于 CompletableFuture.join(),但實際上它會使調用者返回一個承諾(promise)而不是阻塞。

注:當前必須在JDK11中運行。

2.6 Cactoos

Cactoos 是一組面向對象的 Java 基本元素集合。cactoos出現的動機:對 JDK、Guava 和 Apache Commons 并不滿意,因為它們是過程式的,而不是面向對象的。它們能完成工作,但主要是通過靜態方法來實現的。Cactoos 建議幾乎做同樣的事情,但要通過對象來實現。

引入依賴

<dependency>
  <groupId>org.cactoos</groupId>
  <artifactId>cactoos</artifactId>
  <version>0.56.1</version>
</dependency>

使用該庫計算階乘:

public static long factorial(long num) {
  long result = 1 ;
  for (int i = 1; i <= num; i++) {
    result *= i ;
  }
  System.err.println("當前執行線程: " + Thread.currentThread().getName()) ;
  return result ;
}
public static void main(String[] args) throws Exception {
  final long num = 10 ;
  Async<Long, Long> asyncFunction = new Async<>(input -> factorial(input)) ;
  Future<Long> asyncFuture = asyncFunction.apply(num);
  long result = asyncFuture.get() ;
  System.out.printf("%s -> %s 的階乘是: %s%n", Thread.currentThread().getName(), num, result);
}

輸出結果:

當前執行線程: pool-1-thread-1
main -> 10 的階乘是: 3628800

Async構造函數中,默認會創建Executors.newSingleThreadExecutor線程池。

Cactoos 不僅僅是進行異步編程的庫,它還提供了其它非常多的功能,如下示例:

讀取文件

String text = new TextOf(
  new File("d:\\pack.txt")
).asString();

文本格式化

String name = "Spring Boot實戰案例100例" ;
String content = new FormattedText(
    "如何快速提升Spring技能, 必須學習:%s",
    name
  ).asString() ;

詳細更多的示例查看如下鏈接:https://github.com/yegor256/cactoos

2.7 Jcabi-Aspects

Jcabi-Aspects 提供了 @Async 注解,通過 AspectJ AOP 切面實現異步編程。

引入依賴

<dependency>
  <groupId>com.jcabi</groupId>
  <artifactId>jcabi-aspects</artifactId>
  <version>0.26.0</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjrt</artifactId>
  <version>1.9.20.1</version>
</dependency>

配置編譯插件

<plugin>
  <groupId>com.jcabi</groupId>
  <artifactId>jcabi-maven-plugin</artifactId>
  <version>0.17.0</version>
  <executions>
    <execution>
      <goals>
        <goal>ajc</goal>
      </goals>
    </execution>
  </executions>
</plugin>

計算階乘示例:

@Async
public void task(long num) {
  long result = 1 ;
  for (int i = 1; i <= num; i++) {
    result *= i ;
  }
  System.err.printf("%s - 計算結果: %s%n" , Thread.currentThread().getName(), result) ;
}
public static void main(String[] args) throws Exception {
  JcabiAspectTest at = new JcabiAspectTest() ;
  at.task(10L) ;
  System.in.read() ;
}

輸出結果:

jcabi-async - 計算結果: 3628800

配置了jcabi-maven-plugin插件后,在編譯階段會修改對應的字節碼進行代碼的增強。

jcabi-aspects庫不止異步功能,它還提供了其它非常強大的功能。如下的日志記錄功能:

@Async
@Loggable
public void task(long num) {
  // ...
}

當task方法執行時,根據你當前日志配置的級別會輸出相應的日志信息,如下:

圖片圖片


最后:強烈推薦jcabi庫,功能多又強大。

責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2022-07-01 08:00:44

異步編程FutureTask

2024-10-21 13:05:40

2024-12-05 10:37:36

Java純函數final

2011-12-16 14:45:36

JavaJSP

2025-01-15 10:46:23

開發JavaScript集合

2011-05-30 13:37:46

JSP

2010-09-16 17:47:49

2016-09-28 20:05:22

2010-10-15 10:02:01

Mysql表類型

2025-05-13 08:20:58

2014-05-13 09:56:24

數據挖掘

2024-01-02 07:56:13

ReactuseEffect數據驅動 UI

2022-05-24 14:37:49

React條件渲染

2013-01-07 10:14:06

JavaJava枚舉

2009-07-23 16:50:04

2022-10-27 08:09:33

2023-04-18 15:57:30

2024-07-29 08:00:00

2011-03-14 10:46:03

2023-12-22 14:27:30

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品一区二区三区在线观看 | 国产精品不卡 | 精品一二三区 | av影音在线 | 夜夜操天天干 | 欧美中文字幕一区二区 | 正在播放国产精品 | 国产在线中文字幕 | 中文字幕视频一区 | 久久亚洲精品视频 | 国产在线视频三区 | 亚洲午夜精品一区二区三区他趣 | 成人综合视频在线观看 | 99久久久久久 | 国产精品久久久久久久久久免费看 | 国产精品av久久久久久久久久 | 国产精品美女久久久久久久久久久 | 国产精品国产精品 | 亚洲精品乱码久久久久久蜜桃91 | 久久99久久| 久久一区二区三区四区 | 亚洲成网| 久久久久久国产精品mv | 一级大黄 | 国产精品美女www爽爽爽视频 | 日韩中文字幕 | 欧美一级二级视频 | 亚洲人成网站777色婷婷 | 中文字幕欧美一区 | 粉嫩一区二区三区国产精品 | 日韩一区二区三区在线观看 | 日韩欧美国产精品一区二区 | 天堂亚洲网 | 亚洲成人一区二区 | 一区精品在线观看 | 黄色一级视频 | 成人av免费 | 成人av一区| 美女在线观看国产 | 日韩在线 | 国产在线高清 |