37

I am executing a Callable Object using ExecutorService thread pool. I want to give a name to this thread.

To be more specific, in older version I did this -

Thread thread = new Thread(runnable Task);
thread.setName("My Thread Name");

I use thread name in log4j logging, this helps a lot while troubleshooting. Now I am migrating my code from Java 1.4 to Java 1.6. I have written this(Given below)- but I dont know how to give name to this thread.

private final ExecutorService executorPool = Executors.newCachedThreadPool();
Future<String> result = executorPool.submit(callable Task);

Please give me some idea to give name to this thread?

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
user381878
  • 1,543
  • 5
  • 17
  • 30
  • take a look at [`VerboseThreads`](http://www.jcabi.com/jcabi-log/threads-VerboseThreads.html), this factory names threads automatically using provided prefix – yegor256 Jan 02 '13 at 15:50
  • 1
    TL;DR Answer: http://stackoverflow.com/a/9748697/231917 – zengr Jan 29 '13 at 20:08

8 Answers8

44

I'm currently doing it somewhat like this:

    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);
            }
        }
    });
Bart van Heukelom
  • 43,244
  • 59
  • 186
  • 301
  • 6
    this is simple and easy, but since it reverts to the default Thread name at the end of `run()`, you'll only see your custom name while `run()` is executing. for scheduled execution of short-term tasks, you'll see the default name in the debugger most of the time. – ericsoco Jan 11 '13 at 19:31
  • Guava should (but doesn't seem to) have a utility method! – btiernay Nov 07 '13 at 01:37
  • just to be clear, do not forget the finally block.... – Gab Apr 15 '15 at 16:15
29

You may use the overloaded method:

java.util.concurrent.Executors.newCachedThreadPool(ThreadFactory)

which allows you to pass a

java.util.concurrent.ThreadFactory

that should allow you to set the thread's names via java.util.concurrent.ThreadFactory.newThread(Runnable):

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

Have a look at java.util.concurrent.Executors.DefaultThreadFactory for a default implementation.

Addendum

Since I see that this thread is still visited, Guava (if you have it available) provides a ThreadFactoryBuilder that leverages the need of having an inner anonymous class and even allows for customizing parametrized names for your threads.

Andreas
  • 3,929
  • 2
  • 25
  • 22
  • 2
    ThreadFactory.newThread(runnable), but my task is Callable...! – user381878 Jul 12 '10 at 09:13
  • 5
    Your `Callable` will be wrapped into a `java.util.concurrent.FutureTask` that implements `java.util.concurrent.RunnableFuture` that implements `Runnable`. On the other hand it wouldn't make much sense that `ThreadFactory` allows the thread creation only for `Runnable`s whereas `ExecutorService` allows the submission of `Callable`s. – Andreas Jul 12 '10 at 09:28
  • 5
    thanks for your suggestion - I have found another alternative to do that- I am putting this as first line of my thread - Thread.currentThread().setName(this.client.getIdentityString()); – user381878 Jul 12 '10 at 09:35
  • 2
    @user381878, You should heed the warning given by @Shai. Your Callable does not own the Thread it is running on in an ExecutorService. Unless every single Callable and Runnable you submit first changes the Thread's name, then you will eventually get inconsistent logs. – Tim Bender Jul 13 '10 at 00:16
  • 2
    more on this here: http://javahowto.blogspot.com/2011/11/why-use-threadfactory.html – ericsoco Jan 11 '13 at 19:31
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;
    }
}

This is the original implementation in Java 1.5.0. So, you actually have the names as pool-x-thread where x stands for the order of the thread in the current thread group.

MTSan
  • 309
  • 7
  • 10
8

You should be careful when renaming threads when your threads are managed by a thread-pool because they are actually being reused over and over again for different tasks and once renamed, you might find that the thread names in your logs don't make any sense... In order to avoid that unwanted behavior you should make sure that once your Runnable/Callable finished the thread name is restored.

One way to implement this is by wrapping every Runnable/Callable that is executed by the thread-pool with a decorator which handles all of the needed clean-ups.

Shai
  • 113
  • 4
7

If you are using Spring, you may use org.springframework.scheduling.concurrent.CustomizableThreadFactory for that:

ExecutorService executorService = Executors.newCachedThreadPool(
                             new CustomizableThreadFactory("MyThreadNamePrefix"));
Konstantin Pavlov
  • 956
  • 1
  • 10
  • 24
3

I just had to do what you are asking for -- providing names to my thread groups -- so thanks to Andeas's answer, I created my own ThreadFactory as an inner-class to the class that is going to use it by copying Executors$DefaultThreadFactory, changing 3 lines by adding the parameter "groupname" to the constructor.

    /**
 * A thread factory that names each thread with the provided group name.
 * <p>
 * Except lines with "elarson modified", copied from code 
 * Executors$DefaultThreadFactory -- Doug Lea, Copyright Oracle, et al.
 */
static class GroupNameThreadFactory implements ThreadFactory {
    private String groupname; /* elarson modified */
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    GroupNameThreadFactory(String groupname) {
        this.groupname = groupname; /* elarson modified */
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                              Thread.currentThread().getThreadGroup();
        namePrefix = "pool-" +
                       this.groupname + /* elarson modified */
                       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;
    }
}

Creating a ThreadPool from it is done as follows.

        ThreadFactory threadfactory = new GroupNameThreadFactory("Monitor");    
    executor = Executors.newFixedThreadPool(NUM_THREADS, threadfactory);

Thanks user381878 for asking the question, and Andreas for the answer.

Eric Larson
  • 41
  • 1
  • 4
0

Just create an anonymous ThreadFactory for getting the Executor Service. The ThreadFactory can supply the name for the thread as follows: "Thread A" or "Thread B" (see the example).

Then call the callable task using the different executor services:

Example Class:

public class ThreadTester {

public static void main(String[] args) {
    ThreadTester threadTester = new ThreadTester();
    threadTester.test();
}

private void test() {

    ExecutorService executorservice = Executors.newCachedThreadPool(new ThreadFactory() {

        @Override
        public Thread newThread(Runnable arg0) {
            return new Thread(arg0,"Thread A");
        }
    });

    CallableTask taskA = new CallableTask();
    executorservice.submit(taskA);

    executorservice = Executors.newCachedThreadPool(new ThreadFactory() {

        @Override
        public Thread newThread(Runnable arg0) {
            return new Thread(arg0,"Thread B");
        }
    });
    CallableTask taskB = new CallableTask();
    executorservice.submit(taskB);
}

}

Callable Task :

public class CallableTask implements Callable {

@Override
public Integer call() throws Exception {
    int sum = 0;

    for(int count=1;count<=30;count++){
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " Count :"+count);
        sum = sum + count;
    }
    System.out.println(Thread.currentThread().getName() + " Sum :"+sum);
    return sum;
}

}

0

One approach that I've used, and in my case I had a number of futures fetching data in parallel controlled by a single class. I submit a number of jobs and get the futures back. I store the future in a map with the value as the job name. Then later on, when I'm doing a get with a timeout on all futures I have the name of the job from the map. It's not maybe the most flexible way but worked in my situation.