假设我有一个利用Executor框架的应用程序

Executors.newSingleThreadExecutor().submit(new Runnable(){
    @Override
    public void run(){
        // do stuff
    }
}

当我在调试器中运行此应用程序时,将创建一个具有以下(默认)名称的线程:thread [pool-1-thread-1]。正如您所看到的,这并不是非常有用,而且据我所知,Executor框架并没有提供一种简单的方法来命名创建的线程或线程池。

那么,如何为线程/线程池提供名称呢?例如,Thread[fopool - foothread]。


当前回答

你也可以在线程执行之后更改线程的名称:

Thread.currentThread().setName("FooName");

例如,如果您在不同类型的任务中使用相同的ThreadFactory,这可能会很有趣。

其他回答

如果使用Spring,可以为CustomizableThreadFactory设置线程名前缀。

例子:

ExecutorService alphaExecutor =
    Executors.newFixedThreadPool(10, new CustomizableThreadFactory("alpha-"));

或者,您可以使用ThreadPoolExecutorFactoryBean将ExecutorService创建为Spring bean——然后所有线程都将以beanName-前缀命名。

@Bean
public ThreadPoolExecutorFactoryBean myExecutor() {
    ThreadPoolExecutorFactoryBean executorFactoryBean = new ThreadPoolExecutorFactoryBean();
    // configuration of your choice
    return executorFactoryBean;
}

在上面的例子中,线程将以myExecutor-前缀命名。您可以显式地将前缀设置为不同的值(例如。通过在工厂bean上设置executorFactoryBean.setThreadNamePrefix("myPool-")来实现。

Oracle对此有一个开放的RFE。从甲骨文员工的评论来看,他们似乎不理解这个问题,也不会解决。在JDK中支持它是非常简单的事情之一(不会破坏向后兼容性),所以RFE被误解有点遗憾。

如前所述,您需要实现自己的ThreadFactory。如果您不想为了这个目的而引入Guava或Apache Commons,我在这里提供一个ThreadFactory实现供您使用。除了能够将线程名前缀设置为“pool”之外,它与您从JDK中获得的内容完全相似。

package org.demo.concurrency;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * ThreadFactory with the ability to set the thread name prefix. 
 * This class is exactly similar to 
 * {@link java.util.concurrent.Executors#defaultThreadFactory()}
 * from JDK8, except for the thread naming feature.
 *
 * <p>
 * The factory creates threads that have names on the form
 * <i>prefix-N-thread-M</i>, where <i>prefix</i>
 * is a string provided in the constructor, <i>N</i> is the sequence number of
 * this factory, and <i>M</i> is the sequence number of the thread created 
 * by this factory.
 */
public class ThreadFactoryWithNamePrefix implements ThreadFactory {

    // Note:  The source code for this class was based entirely on 
    // Executors.DefaultThreadFactory class from the JDK8 source.
    // The only change made is the ability to configure the thread
    // name prefix.


    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    /**
     * Creates a new ThreadFactory where threads are created with a name prefix
     * of <code>prefix</code>.
     *
     * @param prefix Thread name prefix. Never use a value of "pool" as in that
     *      case you might as well have used
     *      {@link java.util.concurrent.Executors#defaultThreadFactory()}.
     */
    public ThreadFactoryWithNamePrefix(String prefix) {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup()
                : Thread.currentThread().getThreadGroup();
        namePrefix = prefix + "-"
                + poolNumber.getAndIncrement()
                + "-thread-";
    }


    @Override
    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;
    }
}

当您想要使用它时,只需利用所有Executors方法都允许您提供自己的ThreadFactory这一事实。

This

    Executors.newSingleThreadExecutor();

将给出一个ExecutorService,其中线程命名为pool-N-thread-M,但使用

    Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("primecalc"));

您将得到一个ExecutorService,其中线程名为primecalc-N-thread-M。瞧!

您可以尝试提供自己的线程工厂,它将创建具有适当名称的线程。这里有一个例子:

class YourThreadFactory implements ThreadFactory {
   public Thread newThread(Runnable r) {
     return new Thread(r, "Your name");
   }
 }

Executors.newSingleThreadExecutor(new YourThreadFactory()).submit(someRunnable);

或者用Kotlin

Executors.newSingleThreadExecutor { r -> Thread(r, "Your name") }

ThreadFactory扩展

公共接口

根据需要创建新线程的对象。使用线程工厂消除了对新线程的硬连接,使应用程序能够使用特殊的线程子类、优先级等。

线程newThread(可运行r)

构造一个新的线程。实现也可以初始化优先级、名称、守护进程状态、线程组等。

示例代码:

import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy;

class SimpleThreadFactory implements ThreadFactory {
   String name;
   AtomicInteger threadNo = new AtomicInteger(0);

   public SimpleThreadFactory (String name){
       this.name = name;
   }
   public Thread newThread(Runnable r) {
     String threadName = name+":"+threadNo.incrementAndGet();
     System.out.println("threadName:"+threadName);
     return new Thread(r,threadName );
   }
   public static void main(String args[]){
        SimpleThreadFactory factory = new SimpleThreadFactory("Factory Thread");
        ThreadPoolExecutor executor= new ThreadPoolExecutor(1,1,60,
                    TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(1),new ThreadPoolExecutor.DiscardPolicy());


        final ExecutorService executorService = Executors.newFixedThreadPool(5,factory);

        for ( int i=0; i < 100; i++){
            executorService.submit(new Runnable(){
                 public void run(){
                    System.out.println("Thread Name in Runnable:"+Thread.currentThread().getName());
                 }
            });
        }
        executorService.shutdown();
    }
 }

输出:

java SimpleThreadFactory

thread no:1
thread no:2
Thread Name in Runnable:Factory Thread:1
Thread Name in Runnable:Factory Thread:2
thread no:3
thread no:4
Thread Name in Runnable:Factory Thread:3
Thread Name in Runnable:Factory Thread:4
thread no:5
Thread Name in Runnable:Factory Thread:5

根据上面的一些注释,不同之处在于我只使用了lambda

Executors.newFixedThreadPool(10, r -> new Thread(r, "my-threads-%d"))