In this example we shall show you how to make use ThreadFactory
interface, ThreadFactory
is implemented by a user class to override its newThread()
method for on-demand creation of a new thread with a specific configuration like thread name, type(user
, daemon
) and priority, etc.
ThreadFactory vs default ThreadFactory:
In a typical Java ExecutorService
application where some threads will be assigned from the internal thread pool or created on-demand to perform tasks. Each ExecutorService
has an associated ThreadFactory
and a default ThreadFactory
if the application does not specify one. For non-trivial apps, it’s always a good idea to create a custom ThreadFactory
. Why??
- To set a more descriptive thread name. With the default
ThreadFactory
, it gives thread names in the form ofpool-m-thread-n
, such aspool-1-thread-1
,pool-2-thread-1
,pool-3-thread-1
, etc. When analyzing a thread dump, it’s hard to know their purpose and how they were started. So, using a descriptive thread name is the only clue to trace to the source where theThreadPoolExecutor
orExecutorService
is created. - To set thread daemon status. The default
ThreadFactory
produces non-daemon threads. - To set thread priority. The default
ThreadFactory
creates a normal priority threads.
Example:
CustomThreadFactoryBuilder
class is an elegant solution to be able to create customized thread factory instances for more than one thread pool using a thread factory builder mechanism. The ThreadFactory
interface has a single method called newThread(Runnable r)
which accepts a Runnable
type and returns a thread instance. Your factory logic goes into this method implementation where you create and configure the thread instance to set thread name, priority and daemon status, etc.
CustomThreadFactoryBuilder.java:
package com.jcg;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author ashraf
*
*/
public class CustomThreadFactoryBuilder {
private String namePrefix = null;
private boolean daemon = false;
private int priority = Thread.NORM_PRIORITY;
public CustomThreadFactoryBuilder setNamePrefix(String namePrefix) {
if (namePrefix == null) {
throw new NullPointerException();
}
this.namePrefix = namePrefix;
return this;
}
public CustomThreadFactoryBuilder setDaemon(boolean daemon) {
this.daemon = daemon;
return this;
}
public CustomThreadFactoryBuilder setPriority(int priority) {
if (priority = %s", priority,
Thread.MIN_PRIORITY));
}
if (priority > Thread.MAX_PRIORITY) {
throw new IllegalArgumentException(String.format(
"Thread priority (%s) must be <= %s", priority,
Thread.MAX_PRIORITY));
}
this.priority = priority;
return this;
}
public ThreadFactory build() {
return build(this);
}
private static ThreadFactory build(CustomThreadFactoryBuilder builder) {
final String namePrefix = builder.namePrefix;
final Boolean daemon = builder.daemon;
final Integer priority = builder.priority;
final AtomicLong count = new AtomicLong(0);
return new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable);
if (namePrefix != null) {
thread.setName(namePrefix + "-" + count.getAndIncrement());
}
if (daemon != null) {
thread.setDaemon(daemon);
}
if (priority != null) {
thread.setPriority(priority);
}
return thread;
}
};
}
}
SimpleTask
class implements Runnable
interface and prints the running thread properties (name
, priority
).
SimpleTask.java:
package com.jcg;
/**
* @author ashraf
*
*/
public class SimpleTask implements Runnable {
private long sleepTime;
public SimpleTask(long sleepTime) {
super();
this.sleepTime = sleepTime;
}
@Override
public void run() {
while (true) {
try {
System.out.println("Simple task is running on " + Thread.currentThread().getName() + " with priority " + Thread.currentThread().getPriority());
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
CustomThreadFactoryDemo
class creates a new customThreadfactory
using CustomThreadFactoryBuilder
class where we set the thread name prefix to DemoPool-Thread
, daemon status to false
and priority to MAX_PRIORITY
. So, all thread pool threads will be created with these properties. Then, it creates new ExecutorService
to execute three SimpleTask.
CustomThreadFactoryDemo.java:
package com.jcg;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
/**
* @author ashraf
*
*/
public class CustomThreadFactoryDemo {
/**
* @param args
*/
public static void main(String[] args) {
ThreadFactory customThreadfactory = new CustomThreadFactoryBuilder()
.setNamePrefix("DemoPool-Thread").setDaemon(false)
.setPriority(Thread.MAX_PRIORITY).build();
ExecutorService executorService = Executors.newFixedThreadPool(3,
customThreadfactory);
// Create three simple tasks with 1000 ms sleep time
SimpleTask simpleTask1 = new SimpleTask(1000);
SimpleTask simpleTask2 = new SimpleTask(1000);
SimpleTask simpleTask3 = new SimpleTask(1000);
// Execute three simple tasks with 1000 ms sleep time
executorService.execute(simpleTask1);
executorService.execute(simpleTask2);
executorService.execute(simpleTask3);
}
}
Output:
Simple task is running on DemoPool-Thread-0 with priority 10
Simple task is running on DemoPool-Thread-1 with priority 10
Simple task is running on DemoPool-Thread-2 with priority 10
Simple task is running on DemoPool-Thread-0 with priority 10
Simple task is running on DemoPool-Thread-1 with priority 10
Simple task is running on DemoPool-Thread-2 with priority 10
Simple task is running on DemoPool-Thread-0 with priority 10
Simple task is running on DemoPool-Thread-1 with priority 10
Simple task is running on DemoPool-Thread-2 with priority 10
Simple task is running on DemoPool-Thread-0 with priority 10
Simple task is running on DemoPool-Thread-1 with priority 10
Simple task is running on DemoPool-Thread-2 with priority 10
Download the Source Code of this example:
This was an example of how to use Java ThreadFactory
.
You can download the full source code of this example here: ThreadFactoryExampleCode.zip