Java中命名執行器服務執行緒和執行緒池

banq發表於2024-07-08

ExecutorService提供了一種在 Java 中管理執行緒和執行併發任務的便捷方法。使用ExecutorService時,為執行緒和執行緒池分配有意義的名稱有助於改善執行緒的除錯、監控和理解。在本文中,我們將瞭解在 Java 的ExecutorService中命名執行緒和執行緒池的不同方法。

首先,我們將瞭解如何在ExecutorService中設定執行緒的預設名稱。然後,我們將看到使用自定義ThreadFactory、 Apache Commons 的 BasicThreadFactory 和Guava 庫的ThreadFactoryBuilder來自定義執行緒名稱的不同方法。

命名執行緒
如果我們不使用 ExecutorService,則可以輕鬆地在 Java 中設定執行緒名稱。雖然ExecutorService使用預設執行緒池和執行緒名稱(例如“pool-1-thread-1”、“pool-1-thread-2”等) ,但可以為ExecutorService管理的執行緒指定自定義執行緒名稱。

首先,我們來建立一個簡單的程式來執行ExecuterService。稍後,我們將看到它如何顯示預設執行緒和執行緒池名稱:

ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
    executorService.execute(() -> System.out.println(Thread.currentThread().getName()));
}

現在我們執行一下程式,可以看到列印出來的預設執行緒名:

pool-1-thread-1
pool-1-thread-2
pool-1-thread-1
pool-1-thread-3
pool-1-thread-2

使用自定義ThreadFactory
在ExecutorService中,使用ThreadFactory建立新執行緒。ExecutorService使用Executors.defaultThreadFactory建立執行緒來執行任務。

透過向ExecuterService提供不同的自定義ThreadFactory,我們可以改變執行緒的名稱、優先順序等。

首先,讓我們建立自己的實現ThreadFactory 的MyThreadFactory 。然後,我們將為使用MyThreadFactory建立的任何新執行緒建立一個自定義名稱:

public class MyThreadFactory implements ThreadFactory {
    private AtomicInteger threadNumber = new AtomicInteger(1);
    private String threadlNamePrefix = <font>"";
    public MyThreadFactory(String threadlNamePrefix) {
        this.threadlNamePrefix = threadlNamePrefix;
    }
    public Thread newThread(Runnable runnable) {
        return new Thread(runnable, threadlNamePrefix + threadNumber.getAndIncrement());
    }
}

現在,我們將使用自定義工廠MyThreadFactory來設定執行緒名稱並將其傳遞給ExecutorService:

MyThreadFactory myThreadFactory = new MyThreadFactory(<font>"MyCustomThread-");
ExecutorService executorService = Executors.newFixedThreadPool(3, myThreadFactory);
for (int i = 0; i < 5; i++) {
    executorService.execute(() -> System.out.println(Thread.currentThread().getName()));
}

最後,當我們執行程式時,我們可以看到為ExecutorService的執行緒列印的自定義執行緒名稱:

MyCustomThread-1
MyCustomThread-2
MyCustomThread-2
MyCustomThread-3
MyCustomThread-1

使用Apache Commons 的BasicThreadFactory
commons-lang3中的BasicThreadFactory實現了ThreadFactory介面,為執行緒提供了配置選項,有助於設定執行緒名稱。

首先,讓我們將commons-lang3依賴項新增到我們的專案中:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>

接下來,我們使用自定義名稱建立BasicThreadFactory。之後,我們使用工廠建立ExecutorService :

BasicThreadFactory factory = new BasicThreadFactory.Builder()
  .namingPattern(<font>"MyCustomThread-%d").priority(Thread.MAX_PRIORITY).build();
ExecutorService executorService = Executors.newFixedThreadPool(3, factory);
for (int i = 0; i < 5; i++) {
    executorService.execute(() -> System.out.println(Thread.currentThread().getName()));
}

在這裡,我們可以看到namingPattern()方法採用執行緒名稱的名稱模式。

最後,讓我們執行程式來檢視列印的自定義執行緒名稱:

MyCustomThread-1
MyCustomThread-2
MyCustomThread-2
MyCustomThread-3
MyCustomThread-1

使用Guava 中的ThreadFactoryBuilder
Guava 的ThreadFactoryBuilder還提供了自定義其建立的執行緒的選項。

首先,讓我們將guava依賴項新增到我們的專案中:

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

接下來,我們使用自定義名稱建立ThreadFactory ,並將其傳遞給ExecutorService:

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
  .setNameFormat(<font>"MyCustomThread-%d").build();
ExecutorService executorService = Executors.newFixedThreadPool(3, namedThreadFactory);
for (int i = 0; i < 5; i++) {
    executorService.execute(() -> System.out.println(Thread.currentThread().getName()));
}

在這裡,我們可以看到setNameFormat()採用執行緒名稱的名稱模式。

最後,當我們執行程式時,我們可以看到列印的自定義執行緒名稱:

MyCustomThread-0
MyCustomThread-1
MyCustomThread-2
MyCustomThread-2
MyCustomThread-1

這些是我們在使用 Java 中的ExecutorService時命名執行緒的一些方法,可根據應用程式的要求提供靈活性。

相關文章