Naming Threads and Thread-Pools of Executorservice

Naming threads and thread-pools of ExecutorService

You could supply a ThreadFactory to newSingleThreadScheduledExecutor(ThreadFactory threadFactory). The factory will be responsibe for creating threads, and will be able to name them.

To quote the Javadoc:

Creating new threads

New threads are created using a ThreadFactory. If not otherwise specified, a Executors.defaultThreadFactory() is used, that creates threads to all be in the same ThreadGroup and with the same NORM_PRIORITY priority and non-daemon status. By supplying a different ThreadFactory, you can alter the thread's name, thread group, priority, daemon status, etc. If a ThreadFactory fails to create a thread when asked by returning null from newThread, the executor will continue, but might not be able to execute any tasks

How to name the threads of a thread pool in Java

You can pass your own ThreadFactory to ScheduledThreadPoolExecutor. Your ThreadFactory will create thread and can give it any name you want. Your ThreadFactory can also reuse Executors.defaultThreadFactory(), and only change the name before returning the thread.

How to change the name of threads in an ExecutorService?

You'll have to use an ExecutorService implementation that allows you to set the ThreadFactory1 used to create threads, for example, ThreadPoolExecutor. Pass an instance that creates threads with the proper names.

There's also a handy class in commons-lang that allows to specify thread names with a pattern: BasicThreadFactory. This keeps you from having to create a ThreadFactory subclass just to provide the naming behavior.

Finding the Names of active threads inside a threadpool : ExecutorService in java

I was so free to create you a sample, of something I would've done. I couldn't really test it though:

public class CachingThreadFactory implements ThreadFactory{
// amount of active threads at max
private static final int THREAD_POOL_MAX_SIZE = 8;

// interval in milliseconds of the clean up task
private static final int CLEAN_UP_INTERVAL = 2000;

// the actual cache
private final Thread[] cachedThreads = new Thread[THREAD_POOL_MAX_SIZE];

// clean up task definition
{
new Timer().scheduleAtFixedRate(new CleanUpTask(), 0, CLEAN_UP_INTERVAL);
}

@Override
public synchronized Thread newThread(Runnable r){
for(int i = 0; i < cachedThreads.length; i++){
if(cachedThreads[i] == null){
return cachedThreads[i] = new Thread(r, "T" + i);
}
}
return null;
}

private final class CleanUpTask extends TimerTask{
@Override
public void run(){
synchronized(CachingThreadFactory.this){
for(int i = 0; i < cachedThreads.length; i++){
final Thread thread = cachedThreads[i];
if(thread != null && !thread.isAlive()){
cachedThreads[i] = null; // unset
}
}
}
}
}
}

This Factory caches every Thread it creates in an array. Then it runs a cleanUpTask asynchronly which checks if the threads in the array (if any) are still alive. If not they are removed.

The newThread method iterates through the cache, to find an index which is not yet taken, and then uses that index to create the name of that Thread. If no place is free it just returns null.

This class is probably thread safe. But I haven't really tested it. The synchronized-statements should prevent the interference between the cleanUp-Task and the newThread method. But any other action may disturb the whole thing.

Using same instance of ExecutorService in different threads is thread safe?

It look fine. It is a good practice to reuse threads instead of spawning new ones (which is expensive) and one of possible implementations of such thread sharing can be usage of ExecutorService

Just keep in mind, that it will work for the code you have mentioned, It might break if you will try to await for the result of scheduled operation. This can lead to obvious deadlock when all the threads (from the pool) will be waiting for the result of the operation that awaits a free thread (in that pool) to execute it.

How to add prefix in thread names generated through ExecutorService

You can use a custom thread factory, for instance in Ehcache there's one implemented this way:

public class NamedThreadFactory implements ThreadFactory {

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

/**
* Constructor accepting the prefix of the threads that will be created by this {@link ThreadFactory}
*
* @param namePrefix
* Prefix for names of threads
*/
public NamedThreadFactory(String namePrefix) {
this.namePrefix = namePrefix;
}

/**
* Returns a new thread using a name as specified by this factory {@inheritDoc}
*/
public Thread newThread(Runnable runnable) {
return new Thread(runnable, namePrefix + " thread-" + threadNumber.getAndIncrement());
}

}

Then you can create your executor this way:

ExecutorService executor = Executors.newFixedThreadPool(currentRecordSize, new NamedThreadFactory("Your prefix here"));

With ThreadPoolExecutor, how to get the name of the thread running in the thread pool?

Create a ThreadPoolExecutor that overrides the beforeExecute method.

private final ThreadPoolExecutor executor = new ThreadPoolExecutor (new ThreadPoolExecutor(10, 10,  0L, TimeUnit.MILLISECONDS,  new LinkedBlockingQueue<Runnable>()){   
protected void beforeExecute(Thread t, Runnable r) {
t.setName(deriveRunnableName(r));
}

protected void afterExecute(Runnable r, Throwable t) {
Thread.currentThread().setName("");
}

protected <V> RunnableFuture<V> newTaskFor(final Runnable runnable, V v) {
return new FutureTask<V>(runnable, v) {
public String toString() {
return runnable.toString();
}
};
};
}

Not sure how exactly derveRunnableName() would work, maybe toString()?

Edit: The Thread.currentThread() is in fact the thread being set in beforeExecute which calls the afterExecute. You can reference Thread.currentThread() and then set the name in the afterExecute. This is noted in the javadocs

/**
* Method invoked upon completion of execution of the given Runnable.
* This method is invoked by the thread that executed the task. If
* non-null, the Throwable is the uncaught <tt>RuntimeException</tt>
* or <tt>Error</tt> that caused execution to terminate abruptly.
*
* <p><b>Note:</b> When actions are enclosed in tasks (such as
* {@link FutureTask}) either explicitly or via methods such as
* <tt>submit</tt>, these task objects catch and maintain
* computational exceptions, and so they do not cause abrupt
* termination, and the internal exceptions are <em>not</em>
* passed to this method.
*
* <p>This implementation does nothing, but may be customized in
* subclasses. Note: To properly nest multiple overridings, subclasses
* should generally invoke <tt>super.afterExecute</tt> at the
* beginning of this method.
*
* @param r the runnable that has completed.
* @param t the exception that caused termination, or null if
* execution completed normally.
*/
protected void afterExecute(Runnable r, Throwable t) { }

Edit The TPE will wrap the Runnable within a FutureTask, so to support the toString method you could override newTaskFor and create your own wrapped FutureTask.



Related Topics



Leave a reply



Submit