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

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

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

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


当前回答

apache common -lang中的BasicThreadFactory在提供命名行为方面也很有用。您可以使用Builder根据需要命名线程,而不是编写匿名的内部类。下面是来自javadocs的例子:

 // Create a factory that produces daemon threads with a naming pattern and
 // a priority
 BasicThreadFactory factory = new BasicThreadFactory.Builder()
     .namingPattern("workerthread-%d")
     .daemon(true)
     .priority(Thread.MAX_PRIORITY)
     .build();
 // Create an executor service for single-threaded execution
 ExecutorService exec = Executors.newSingleThreadExecutor(factory);

其他回答

我用来装饰现有工厂的自制核心Java解决方案:

public class ThreadFactoryNameDecorator implements ThreadFactory {
    private final ThreadFactory defaultThreadFactory;
    private final String suffix;

    public ThreadFactoryNameDecorator(String suffix) {
        this(Executors.defaultThreadFactory(), suffix);
    }

    public ThreadFactoryNameDecorator(ThreadFactory threadFactory, String suffix) {
        this.defaultThreadFactory = threadFactory;
        this.suffix = suffix;
    }

    @Override
    public Thread newThread(Runnable task) {
        Thread thread = defaultThreadFactory.newThread(task);
        thread.setName(thread.getName() + "-" + suffix);
        return thread;
    }
}

在行动:

Executors.newSingleThreadExecutor(new ThreadFactoryNameDecorator("foo"));

您可以编写自己的ThreadFactory实现,例如使用一些现有的实现(如defaultThreadFactory),并在最后更改名称。

实现ThreadFactory的例子:

class ThreadFactoryWithCustomName implements ThreadFactory {
    private final ThreadFactory threadFactory;
    private final String name;

    public ThreadFactoryWithCustomName(final ThreadFactory threadFactory, final String name) {
        this.threadFactory = threadFactory;
        this.name = name;
    }

    @Override
    public Thread newThread(final Runnable r) {
        final Thread thread = threadFactory.newThread(r);
        thread.setName(name);
        return thread;
    }
}

和用法:

Executors.newSingleThreadExecutor(new ThreadFactoryWithCustomName(
        Executors.defaultThreadFactory(),
        "customName")
    );
Executors.newSingleThreadExecutor(r -> new Thread(r, "someName")).submit(getJob());

Runnable getJob() {
        return () -> {
            // your job
        };
}

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

如果使用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-")来实现。