[java] Naming threads and thread-pools of ExecutorService

Let's say I have an application that utilizes the Executor framework as such

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

When I run this application in the debugger, a thread is created with the following (default) name: Thread[pool-1-thread-1]. As you can see, this isn't terribly useful and as far as I can tell, the Executor framework does not provide an easy way to name the created threads or thread-pools.

So, how does one go about providing names for the threads/thread-pools? For instance, Thread[FooPool-FooThread].

The answer is


A quick and dirty way is to use Thread.currentThread().setName(myName); in the run() method.


The BasicThreadFactory from apache commons-lang is also useful to provide the naming behavior. Instead of writing an anonymous inner class, you can use the Builder to name the threads as you want. Here's the example from the 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);

There's an open RFE for this with Oracle. From the comments from the Oracle employee it seems they don't understand the issue and won't fix. It's one of these things that is dead simple to support in the JDK (without breaking backwards compatibility) so it is kind of a shame that the RFE gets misunderstood.

As pointed out you need to implement your own ThreadFactory. If you don't want to pull in Guava or Apache Commons just for this purpose I provide here a ThreadFactory implementation that you can use. It is exactly similar to what you get from the JDK except for the ability to set the thread name prefix to something else than "pool".

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

When you want to use it you simply take advantage of the fact that all Executors methods allow you to provide your own ThreadFactory.

This

    Executors.newSingleThreadExecutor();

will give an ExecutorService where threads are named pool-N-thread-M but by using

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

you'll get an ExecutorService where threads are named primecalc-N-thread-M. Voila!


The home-grown core Java solution that I use to decorate existing factories:

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

In action:

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

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

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

You can write your own implementation of ThreadFactory, using for example some existing implementation (like defaultThreadFactory) and change the name at the end.

Example of implementing 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;
    }
}

And usage:

Executors.newSingleThreadExecutor(new ThreadFactoryWithCustomName(
        Executors.defaultThreadFactory(),
        "customName")
    );

Using the existing functionality of Executors.defaultThreadFactory() but just setting the name:

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class NamingThreadFactory implements ThreadFactory {
    private final String prefix;
    private int threadNuber = 0;

    public NamingThreadFactory(String prefix){
        this.prefix = prefix;
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = Executors.defaultThreadFactory().newThread(r);
        t.setName(prefix + threadNuber);
        return t;
    }
}

If you are using Spring, there is CustomizableThreadFactory for which you can set a thread name prefix.

Example:

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

Alternatively, you can create your ExecutorService as a Spring bean using ThreadPoolExecutorFactoryBean - then the threads will all be named with the beanName- prefix.

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

In the example above, the threads will be named with myExecutor- prefix. You can set the prefix explicitly to a different value (eg. "myPool-") by setting executorFactoryBean.setThreadNamePrefix("myPool-") on the factory bean.


Based on few of the comments above, difference is I just used lambda

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

This is my customized factory providing a customized names for thread dump analyzers. Usually I just give tf=null to reuse JVM default thread factory. This website has more advanced thread factory.

public class SimpleThreadFactory implements ThreadFactory {
    private ThreadFactory tf;
    private String nameSuffix;

    public SimpleThreadFactory (ThreadFactory tf, String nameSuffix) {
        this.tf = tf!=null ? tf : Executors.defaultThreadFactory();
        this.nameSuffix = nameSuffix; 
    }

    @Override public Thread newThread(Runnable task) {
        // default "pool-1-thread-1" to "pool-1-thread-1-myapp-MagicTask"
        Thread thread=tf.newThread(task);
        thread.setName(thread.getName()+"-"+nameSuffix);
        return thread;
    }
}

- - - - - 

ExecutorService es = Executors.newFixedThreadPool(4, new SimpleThreadFactory(null, "myapp-MagicTask") );

For your convenience this is a thread dump loop for debug purpose.

    ThreadMXBean mxBean=ManagementFactory.getThreadMXBean();
    long[] tids = mxBean.getAllThreadIds();
    System.out.println("------------");
    System.out.println("ThreadCount="+tids.length);
    for(long tid : tids) {
        ThreadInfo mxInfo=mxBean.getThreadInfo(tid);
        if (mxInfo==null) {
            System.out.printf("%d %s\n", tid, "Thread not found");
        } else {
            System.out.printf("%d %s, state=%s, suspended=%d, lockowner=%d %s\n"
                    , mxInfo.getThreadId(), mxInfo.getThreadName()
                    , mxInfo.getThreadState().toString()
                    , mxInfo.isSuspended()?1:0
                    , mxInfo.getLockOwnerId(), mxInfo.getLockOwnerName()
            );
        }
    }

private class TaskThreadFactory implements ThreadFactory
{

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r, "TASK_EXECUTION_THREAD");

        return t;
    }

}

Pass the ThreadFactory to an executorservice and you are good to go


You can also change the name of your thread afterwards, while the thread is executed:

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

That could be of interest if for instance you're using the same ThreadFactory for different type of tasks.


You can try to provide your own thread factory, which will create thread with appropriate names. Here's one example:

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

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

Guava almost always has what you need.

ThreadFactory namedThreadFactory = 
  new ThreadFactoryBuilder().setNameFormat("my-sad-thread-%d").build()

and pass it off to your ExecutorService.


I find it easiest to use a lambda as a thread factory if you just want to change the name for a single thread executor.

Executors.newSingleThreadExecutor(runnable -> new Thread(runnable, "Your name"));

Extend ThreadFactory

public interface ThreadFactory

An object that creates new threads on demand. Using thread factories removes hardwiring of calls to new Thread, enabling applications to use special thread subclasses, priorities, etc.

Thread newThread(Runnable r)

Constructs a new Thread. Implementations may also initialize priority, name, daemon status, ThreadGroup, etc.

Sample code:

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();
    }
 }

output:

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

....etc


As other answers already said, you may create and use your own implementation of the java.util.concurrent.ThreadFactory interface (no external libraries required). I am pasting my code below because it is different than previous answers since it uses String.format method and takes a base name for the threads as a constructor argument:

import java.util.concurrent.ThreadFactory;

public class NameableThreadFactory implements ThreadFactory{
    private int threadsNum;
    private final String namePattern;

    public NameableThreadFactory(String baseName){
        namePattern = baseName + "-%d";
    }

    @Override
    public Thread newThread(Runnable runnable){
        threadsNum++;
        return new Thread(runnable, String.format(namePattern, threadsNum));
    }    
}

And this is an example of usage:

ThreadFactory  threadFactory = new NameableThreadFactory("listenerThread");        
final ExecutorService executorService = Executors.newFixedThreadPool(5, threadFactory);

EDIT: making my ThreadFactory implementation thread-safe, thanks to @mchernyakov for pointing it out.
Even though nowhere in the ThreadFactory documentation is said that its implementations must be thread-safe, the fact that the DefaultThreadFactory is thread-safe is a big hint:

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

public class NameableThreadFactory implements ThreadFactory{
    private final AtomicInteger threadsNum = new AtomicInteger();

    private final String namePattern;

    public NameableThreadFactory(String baseName){
        namePattern = baseName + "-%d";
    }

    @Override
    public Thread newThread(Runnable runnable){
        return new Thread(runnable, String.format(namePattern, threadsNum.addAndGet(1)));
    }    
}

Thought I'd throw in some simplified examples, just so the options are all out there:

Unique number (could also put this into a method):

AtomicInteger threadNum = new AtomicInteger(0);
ExecutorService e = Executors.newSingleThreadExecutor(r -> new Thread(r, "my-name-" + threadNum.incrementAndGet()));

Unique number and "probably" unique name (if you're generating new Runnable objects). Useful if starting off the threads is within a method that gets called more than once, for instance:

AtomicInteger threadNum = new AtomicInteger(0);
ExecutorService e = Executors.newSingleThreadExecutor(r -> new Thread(r, "my-name-" + threadNum.incrementAndGet() + "-" + r.hashCode()));

If you really wanted a unique name each time you'd need a class with a static var (and could also add a static pool number prefix in there as well, see other answers).

and an equivalent in JDK < 8 (you don't need a new class for it, or could return a ThreadFactory out of a method):

Executors.newSingleThreadExecutor(new ThreadFactory() {
      AtomicInteger threadCount = new AtomicInteger(0);

      @Override
      public Thread newThread(Runnable r) {
        return new Thread(r, "your-name-" + threadCount.getAndIncrement() + "-" + r.hashCode()); // could also use Integer.toHexString(r.hashCode()) for shorter
      }
    }));

And could make that into a method for the "you-name-" aspect as a variable. Or use a separate class with a constructor like the other answers all seem to.


I use to do same like below (requires guava library) :

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("SO-POOL-%d").build();
ExecutorService executorService = Executors.newFixedThreadPool(5,namedThreadFactory);

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to threadpool

Thread pooling in C++11 If my interface must return Task what is the best way to have a no-operation implementation? How can I shutdown Spring task executor/scheduler pools before all other beans in the web app are destroyed? How to increase number of threads in tomcat thread pool? Naming threads and thread-pools of ExecutorService How to get thread id from a thread pool? ExecutorService, how to wait for all tasks to finish How many threads is too many?

Examples related to runnable

In a simple to understand explanation, what is Runnable in Java? new Runnable() but no new thread? What's the difference between Thread start() and Runnable run() Naming threads and thread-pools of ExecutorService Runnable with a parameter? "implements Runnable" vs "extends Thread" in Java The difference between the Runnable and Callable interfaces in Java

Examples related to executorservice

Naming threads and thread-pools of ExecutorService How to get thread id from a thread pool? ExecutorService, how to wait for all tasks to finish ExecutorService that interrupts tasks after a timeout Handling exceptions from Java ExecutorService tasks How to wait for all threads to finish, using ExecutorService? Executors.newCachedThreadPool() versus Executors.newFixedThreadPool() Java Timer vs ExecutorService?

Examples related to managedthreadfactory

Naming threads and thread-pools of ExecutorService