Open In App

ThreadFactory Interface in Java with Examples

Improve
Improve
Like Article
Like
Save
Share
Report

The ThreadFactory interface defined in the java.util.concurrent package is based on the factory design pattern. As its name suggests, it is used to create new threads on demand. Threads can be created in two ways:

1. Creating a class that extends the Thread class and then creating its objects.

Java




import java.io.*;
 
class GFG {
   
    public static void main(String[] args)
    {
        // Creating a thread
        Thread thread = new CustomThread();
        thread.start(); // Starting execution of the created
                        // thread
    }
}
 
// Creating a class that extends the Thread class
class CustomThread extends Thread {
    @Override public void run()
    {
        System.out.println("This is a thread");
    }
}


 
 

Output

This is a thread

 

2. Creating a class that implements the Runnable interface and then using its object to create threads.

 

Java




/*package whatever //do not write package name here */
 
import java.io.*;
 
class GFG {
    public static void main(String[] args)
    {
        // Creating a Runnable object
        Runnable task = new Task();
        // Creating a thread using the Runnable object
        Thread thread = new Thread(task);
        // Starting the execution of the created thread
        thread.start();
    }
}
 
class Task implements Runnable {
    @Override public void run()
    {
        System.out.println("This is a thread");
    }
}


 
 

Output

This is a thread

 

However, ThreadFactory is another choice to create new threads. This interface provides a factory method that creates and returns new threads when called. This factory method takes a Runnable object as an argument and creates a new thread using it.

 

The Hierarchy of ThreadFactory

 

java.util.concurrent
    ↳ Interface ThreadFactory

 

Implementation of ThreadFactory interface

 

 Since ThreadFactory is an interface, the factory method defined inside it has to be implemented first in order to be used. Here is the simplest implementation of the ThreadFactory interface :  

 

Java




import java.util.concurrent.ThreadFactory;
import java.io.*;
 
class CustomThreadFactory implements ThreadFactory {
 
    // newThread is a factory method
    // provided by ThreadFactory
    public Thread newThread(Runnable command)
    {
        return new Thread(command);
    }
}


 

 

Now, we can create objects of the CustomThreadFactory class and use its newThread(Runnable command) method to create new threads on demand. In the above implementation, the newThread method just creates a new thread by calling the Thread constructor which takes a Runnable command as the parameter.

 

There are many classes(such as ScheduledThreadPoolExecutor , ThreadPoolExecutor etc.) that use thread factories to create new threads when needed. Those classes have constructors that accept a ThreadFactory as argument. If any custom ThreadFactory is not given then they use the default implementation of ThreadFactory interface. 

 

The Executors class in java.util.concurrent package provides Executors.defaultThreadFactory() static method that returns a default implementation of ThreadFactory interface.

 

Example: Below example code demonstrates ThreadFactory interface.

 

Java




// Java code to demonstrate ThreadFactory interface
 
import java.util.concurrent.ThreadFactory;
import java.io.*;
import java.util.ArrayList;
 
class ThreadFactoryExample {
    public static void main(String[] args)
    {
        // Creating a CustomThreadFactory object
        CustomThreadFactory threadFactory
            = new CustomThreadFactory();
 
        // Creating Runnable objects using the lambda
        // expression
        Runnable command1 = ()
            -> System.out.println("Command 1 executed");
        Runnable command2 = ()
            -> System.out.println("Command 2 executed");
        Runnable command3 = ()
            -> System.out.println("Command 3 executed");
        Runnable command4 = ()
            -> System.out.println("Command 4 executed");
        Runnable command5 = ()
            -> System.out.println("Command 5 executed");
 
        // Putting the commands in an ArrayList
        ArrayList<Runnable> array = new ArrayList<>(5);
        array.add(command1);
        array.add(command2);
        array.add(command3);
        array.add(command4);
        array.add(command5);
 
        // creating threads and running them
        for (Runnable command : array) {
            threadFactory.newThread(command).start();
        }
 
        // print the thread count
        System.out.println(
            "Total number of threads created using CustomThreadFactory = "
            + threadFactory.getCount());
    }
}
 
// ThreadFactory class
class CustomThreadFactory implements ThreadFactory {
 
    // stores the thread count
    private int count = 0;
 
    // returns the thread count
    public int getCount() { return count; }
 
    // Factory method
    @Override
      public Thread newThread(Runnable command)
    {
        count++;
        return new Thread(command);
    }
}


 
 

Output

Command 1 executed
Command 2 executed
Command 4 executed
Command 3 executed
Command 5 executed
Total number of threads created using CustomThreadFactory = 5

 

Why use ThreadFactory?

 

In the above example, the newThread(Runnable) factory method ultimately creates a new thread using the given Runnable command. Then why use ThreadFactory? We could directly create threads from the Runnable commands by calling the Thread constructor that we did in the newThread(Runnable) method. Here are some reasons,

 

  • We can give the threads more meaningful custom names. It helps in analyzing their purposes and how they work.
  • We can have the statistics about the created threads like the count of threads and other details. We can restrict the creation of new threads based on the statistics.
  • We can set the daemon status of threads.
  • We can set the thread priority.
  • We can have all the features confined in one class.

 

Default Thread Factory

 

It is the default thread factory that is implemented by the Executors.defaultThreadFactory() static method. This default ThreadFactory is used by many classes (such as ScheduledThreadPoolExecutor, ThreadPoolExecutor etc.) when they are not given any custom ThreadFactory. Those classes create new threads using the default ThreadFactory. This default ThreadFactory creates all the new threads in the same ThreadGroup(A ThreadGroup represents a group of threads). All the created new threads are non-daemon with priority set to the smallest of Thread.NORM_PRIORITY and the maximum priority permitted in the ThreadGroup. The threads created by this default ThreadFactory are given names in the form of pool-N-thread-M (As examples, pool-1-thread-1, pool-1-thread-2, pool-2-thread-1 etc.) where N is the sequence number of this factory, and M is the sequence number of the threads created by this factory.

 

Example: The below example demonstrates how the default ThreadFactory can be used. 

 

Java




// Java program to demonstrate default
// ThreadFactory
 
import java.io.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
 
class DefaultThreadFactoryExample {
    public static void main(String[] args)
    {
        // Default ThreadFactory
        ThreadFactory threadFactory
            = Executors.defaultThreadFactory();
 
        for (int i = 1; i < 10; i++) {
 
            // Creating new threads with the default
            // ThreadFactory
            Thread thread
                = threadFactory.newThread(new Command());
 
            // print the thread names
            System.out.println(
                "Name given by threadFactory = "
                + thread.getName());
 
            // run the thread
            thread.start();
        }
    }
}
 
class Command implements Runnable {
 
    @Override public void run()
    {
        // Run some code
    }
}


 
 

Output

Name given by threadFactory = pool-1-thread-1
Name given by threadFactory = pool-1-thread-2
Name given by threadFactory = pool-1-thread-3
Name given by threadFactory = pool-1-thread-4
Name given by threadFactory = pool-1-thread-5
Name given by threadFactory = pool-1-thread-6
Name given by threadFactory = pool-1-thread-7
Name given by threadFactory = pool-1-thread-8
Name given by threadFactory = pool-1-thread-9

 

Note the names of threads given by default ThreadFactory. It has created 9 threads and all the threads are in the same ThreadGroup. All the threads are created using the same ThreadFactory(so the names of the threads are in form of pool -1 -thread-M).

 

Example: 

 

Java




// Java program to demonstrate ThreadFactory
// using default implementation
 
import java.io.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
 
class DefaultThreadFactoryExample {
    public static void main(String[] args)
    {
 
        for (int i = 1; i < 10; i++) {
 
            // Default ThreadFactory
            ThreadFactory threadFactory
                = Executors.defaultThreadFactory();
 
            // Creating new threads with the default
            // ThreadFactory
            Thread thread
                = threadFactory.newThread(new Command());
 
            // print the thread name
            System.out.println(
                "Name given by threadFactory = "
                + thread.getName());
 
            // start the thread
            thread.start();
        }
    }
}
 
class Command implements Runnable {
    @Override public void run()
    {
        // Run some code
    }
}


 
 

Output

Name given by threadFactory = pool-1-thread-1
Name given by threadFactory = pool-2-thread-1
Name given by threadFactory = pool-3-thread-1
Name given by threadFactory = pool-4-thread-1
Name given by threadFactory = pool-5-thread-1
Name given by threadFactory = pool-6-thread-1
Name given by threadFactory = pool-7-thread-1
Name given by threadFactory = pool-8-thread-1
Name given by threadFactory = pool-9-thread-1

 

Here, We have used 9 different default ThreadFactories(in each loop we are creating a new one!). So each thread is in different ThreadGroup and thus the threads are given name in form of pool-N-thread-1.

 

The default ThreadFactory implementation creates non-daemon threads with normal priority and gives names in form of pool-N-thread-M which contains no information about how they work and what they do. This creates lots of problems in debugging and other important purposes. However, this problem can be solved using a custom ThreadFactory which can give more meaningful names to the threads and can set the daemon and priority statuses.

 

Methods of ThreadFactory

METHOD

DESCRIPTION

newThread​(Runnable r) Constructs a new Thread.

 



Last Updated : 24 Jun, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads