我们的软件倾向于使用大量的线程池——主要是通过java.util.concurrent.ExecutorService
实现(通过Executors.new...
创建)。我们为各种异步用例创建这些线程池,它们随处可见。所有这些执行器都有一个线程工厂。它隐藏在默认工厂方法,但您可以提供线程工厂。如果未提供,则在需要线程时使用默认线程工厂。
使用 spring 时,可以使用<task:executor />
。在这种情况下,每个执行程序服务的线程工厂由 spring 提供,它使用执行程序 bean 的名称(用id="executorName"
指定)。但是对于那些不是由 spring 创建的,使用默认名称是没有帮助的,并且不允许您按名称区分线程。
并且您需要按名称区分线程——如果出现性能问题,您有多种调查选项:线程转储和使用 top 命令。在这两种情况下,了解线程服务的函数是有用的,因为转储中的堆栈跟踪可能并不总是显示出来。
我最喜欢的快速调查工具是top
,更准确地说,top -H -p <pid>
。这显示了通常的顶部表,但 -H
标志意味着应该打印所选进程的线程。按名称,您基本上会获得占用 CPU 最多且当前处于活动状态的线程。在这些情况下,自定义名称非常有用。
但是如何设置名称呢?通过在创建每个执行程序时指定一个命名的线程工厂。
我使用的方法基于第二个答案:
public class AsyncUtils {
public static ThreadFactory createNamedThreadFactory(String name) {
return new ThreadFactoryBuilder().setNameFormat(name + "-%d").build();
}
}
通过 spring 集中管理所有 executor 可能是一个更好的主意,但并不是每个人都在使用 spring,有时甚至可能超出 spring bean 的一小部分功能需要一个 executor。因此,这是一个很好的方法。