Creating a custom thread factory in Java is a powerful way to manage how threads are initialized. Instead of using the default factory, you can customize thread names (vital for debugging!), set priority levels, or even create daemon threads.
To do this, you need to implement the java.util.concurrent.ThreadFactory interface.
1. Implement the ThreadFactory Interface
The interface has a single method: newThread(Runnable r). Here is a clean, reusable example:
package org.kodejava.util.concurrent;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class CustomThreadFactory implements ThreadFactory {
private final String namePrefix;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final boolean daemon;
public CustomThreadFactory(String poolName, boolean daemon) {
this.namePrefix = poolName + "-worker-";
this.daemon = daemon;
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());
t.setDaemon(daemon);
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
2. Use the Factory with an ExecutorService
Once you’ve defined your factory, you can pass it to any ThreadPoolExecutor or static Executors factory method. This ensures every thread created by that pool follows your rules.
package org.kodejava.util.concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadFactoryDemo {
public static void main(String[] args) {
// Create the factory
CustomThreadFactory factory = new CustomThreadFactory("OrderProcessor", false);
// Pass it to a Fixed Thread Pool
ExecutorService executor = Executors.newFixedThreadPool(3, factory);
for (int i = 0; i < 5; i++) {
executor.submit(() -> {
System.out.println("Running task in: " + Thread.currentThread().getName());
});
}
executor.shutdown();
}
}
Why use a custom factory?
- Identifiability: In thread dumps or logs, seeing
OrderProcessor-worker-1is much more helpful thanpool-1-thread-1. - Security & Cleanup: You can set
setDaemon(true)for background cleanup tasks so they don’t prevent the JVM from shutting down. - Context: You can use the factory to inject
ThreadLocalvariables or set a customUncaughtExceptionHandlerfor all threads in a pool.
