如何为可调用线程命名?

use*_*878 35 java multithreading executorservice java.util.concurrent

我正在使用ExecutorService线程池执行可调用对象.我想给这个帖子命名.

更具体地说,在旧版本中,我这样做了 -

Thread thread = new Thread(runnable Task);
thread.setName("My Thread Name");
Run Code Online (Sandbox Code Playgroud)

我在log4j日志记录中使用线程名称,这在故障排除时有很大帮助.现在我将我的代码从Java 1.4迁移到Java 1.6.我写了这个(在下面给出) - 但我不知道如何给这个帖子命名.

private final ExecutorService executorPool = Executors.newCachedThreadPool();
Future<String> result = executorPool.submit(callable Task);
Run Code Online (Sandbox Code Playgroud)

请给我一些想法给这个帖子命名?

Bar*_*lom 37

我目前正在这样做:

    someExecutor.execute(new Runnable() {
        @Override public void run() {
            final String orgName = Thread.currentThread().getName();
            Thread.currentThread().setName(orgName + " - My custom name here");
            try {
                myAction();
            } finally {
                Thread.currentThread().setName(orgName);
            }
        }
    });
Run Code Online (Sandbox Code Playgroud)

  • 这很简单,但是由于它在`run()`的末尾恢复为默认的Thread名称,所以只有在`run()`执行时才会看到你的自定义名称.对于计划执行的短期任务,您将在大多数时间看到调试器中的默认名称. (4认同)

And*_*eas 29

您可以使用重载方法:

java.util.concurrent.Executors.newCachedThreadPool(ThreadFactory)
Run Code Online (Sandbox Code Playgroud)

它允许你通过

java.util.concurrent.ThreadFactory
Run Code Online (Sandbox Code Playgroud)

应该允许您通过以下方式设置线程的名称java.util.concurrent.ThreadFactory.newThread(Runnable):

构造一个新的Thread.实现还可以初始化优先级,名称,守护程序状态ThreadGroup等.

看一下java.util.concurrent.Executors.DefaultThreadFactory默认实现.

附录

因为我看到仍然访问了这个线程,Guava(如果你有它)提供了一个 ThreadFactoryBuilder,它利用了内部匿名类的需要,甚至允许为你的线程自定义参数化名称.

  • 你的`Callable`将被包装成一个`java.util.concurrent.FutureTask`,它实现了`java.util.concurrent.RunnableFuture`,它实现了`Runnable`.另一方面,'ThreadFactory`只允许为'Runnable'创建线程,而`ExecutorService`允许提交`Callable`s',这没有多大意义. (5认同)
  • 感谢您的建议 - 我找到了另一种方法 - 我将它作为我的线程的第一行 - Thread.currentThread().setName(this.client.getIdentityString()); (4认同)
  • ThreadFactory.newThread(runnable),但我的任务是 Callable...! (2认同)
  • @ user381878,你应该留意@Shai给出的警告.您的Callable不拥有它在ExecutorService中运行的线程.除非您首先提交的每个Callable和Runnable都更改了Thread的名称,否则最终会得到不一致的日志. (2认同)
  • 更多关于这一点:http://javahowto.blogspot.com/2011/11/why-use-threadfactory.html (2认同)

MTS*_*San 10

/**
 * The default thread factory
 */
static class DefaultThreadFactory implements ThreadFactory {
    static final AtomicInteger poolNumber = new AtomicInteger(1);
    final ThreadGroup group;
    final AtomicInteger threadNumber = new AtomicInteger(1);
    final String namePrefix;

    DefaultThreadFactory() {
        SecurityManager s = System.getSecurityManager();
        group = (s != null)? s.getThreadGroup() :
                             Thread.currentThread().getThreadGroup();
        namePrefix = "pool-" + 
                      poolNumber.getAndIncrement() + 
                     "-thread-";
    }

    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r, 
                              namePrefix + threadNumber.getAndIncrement(),
                              0);
        if (t.isDaemon())
            t.setDaemon(false);
        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
        return t;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是Java 1.5.0中的原始实现.因此,您实际上将名称设置为pool-x-thread,其中x代表当前线程组中线程的顺序.


小智 8

重命名线程时,当你的线程由一个线程池来管理,因为他们实际上是被重用一遍一遍不同的任务,一旦改名,你就要小心了,你可能会发现,在你的日志线程名称没有任何意义...为了避免这种不必要的行为,您应该确保在Runnable/Callable完成后恢复线程名称.

实现这一点的一种方式是通过包裹由线程池负责处理所有必要的清理工作的装饰每次执行的Runnable /赎回.


Kon*_*lov 7

如果您使用的是Spring,可以使用org.springframework.scheduling.concurrent.CustomizableThreadFactory:

ExecutorService executorService = Executors.newCachedThreadPool(
                             new CustomizableThreadFactory("MyThreadNamePrefix"));
Run Code Online (Sandbox Code Playgroud)