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 = ""; 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("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("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("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时命名线程的一些方法,可根据应用程序的要求提供灵活性。