ThreadFactory Interface in Java with Examples


Introduction

The ThreadFactory interface in Java is a vital component of multithreaded programming. This powerful interface creates a new thread on demand and can be customized to suit different requirements. This article aims to provide a comprehensive understanding of this interface, along with several practical examples. By the end of this piece, you'll have a firm grasp on the ThreadFactory interface and its usage in Java programming.

Understanding Java ThreadFactory Interface

Before delving into examples, let's start by understanding the basic concepts.

What is the ThreadFactory Interface?

The ThreadFactory interface is part of Java's java.util.concurrent package. It's designed to create new threads, and it's typically used in conjunction with executor services and thread pools, where creating threads on-the-fly is a common requirement.

Why use ThreadFactory?

The ThreadFactory interface offers much more control over thread creation compared to directly instantiating the Thread class. You can customize the thread's name, its priority, its daemon status, and even what to do when the thread is uncaught by an exception. This level of control is crucial when dealing with complex multithreaded systems.

Implementing ThreadFactory Interface in Java

The ThreadFactory interface has only one method, newThread(), which needs to be overridden when implementing the interface.

Example

Here's a simple example −

import java.util.concurrent.ThreadFactory;

public class SimpleThreadFactory implements ThreadFactory {
   private int threadId;
   private String name;

   public SimpleThreadFactory(String name) {
       threadId = 1;
       this.name = name;
   }

   @Override
   public Thread newThread(Runnable r) {
       Thread t = new Thread(r, name + "-Thread_" + threadId);
       System.out.println("Created new thread with ID: " + threadId + " and name: " + t.getName());
       threadId++;
       return t;
   }

   public static void main(String[] args) {
      SimpleThreadFactory threadFactory = new SimpleThreadFactory("MyThread");
        
      // Create a new runnable task
      Runnable task = () -> {
          System.out.println("Running task in thread: " + Thread.currentThread().getName());
      };
        
      // Create threads using the thread factory
      Thread thread1 = threadFactory.newThread(task);
      Thread thread2 = threadFactory.newThread(task);
        
      // Start the threads
      thread1.start();
      thread2.start();
   }
}

Output

Created new thread with ID: 1 and name: MyThread-Thread_1
Created new thread with ID: 2 and name: MyThread-Thread_2
Running task in thread: MyThread-Thread_1
Running task in thread: MyThread-Thread_2

In this example, the ‘SimpleThreadFactory’ implements the ThreadFactory interface and provides a basic functionality of creating a new thread with a unique name.

Applying the ThreadFactory Interface

Now, let's see the ThreadFactory interface in action. In this example, we're going to use our SimpleThreadFactory with an executor service to create and run several tasks.

Example

import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;

public class Main {
   public static void main(String[] args) {
      SimpleThreadFactory factory = new SimpleThreadFactory("Test");
      ExecutorService executor = Executors.newFixedThreadPool(5, factory);

      for (int i = 0; i < 10; i++) {
         Runnable worker = new WorkerThread("" + i);
         executor.execute(worker);
      }

      executor.shutdown();
      while (!executor.isTerminated()) {
      }

      System.out.println("All threads finished");
   }
}
class WorkerThread implements Runnable {
   private String command;

   public WorkerThread(String s) {
       this.command = s;
   }

   @Override
   public void run() {
     System.out.println(Thread.currentThread().getName() + " Start. Command = " + command);
       processCommand();
     System.out.println(Thread.currentThread().getName() + " End.");
   }

   private void processCommand() {
     try {
         Thread.sleep(5000);
     } catch (InterruptedException e) {
         e.printStackTrace();
      }
   }
}
class SimpleThreadFactory implements ThreadFactory {
   private final String namePrefix;

   public SimpleThreadFactory(String namePrefix) {
      this.namePrefix = namePrefix;
   }

   @Override
   public Thread newThread(Runnable r) {
      Thread t = new Thread(r);
      t.setName(namePrefix + "-" + t.getId());
      return t;
   }
}

Output

Test-23 Start. Command = 0
Test-26 Start. Command = 3
Test-25 Start. Command = 2
Test-24 Start. Command = 1
Test-27 Start. Command = 4
Test-27 End.
Test-24 End.
Test-23 End.
Test-25 End.
Test-26 End.
Test-23 Start. Command = 7
Test-24 Start. Command = 6
Test-27 Start. Command = 5
Test-25 Start. Command = 8
Test-26 Start. Command = 9

In the Main class, we've created an ExecutorService with a fixed thread pool of size 5 and our custom SimpleThreadFactory. We then submit 10 WorkerThread tasks to the executor. Each task simulates a delay of 5 seconds to mimic processing time.

Advanced Usage of ThreadFactory

Let's take a look at a more advanced ThreadFactory that sets the priority of the thread and also sets the threads as daemon threads.

import java.util.concurrent.ThreadFactory;

public class AdvancedThreadFactory implements ThreadFactory {
   private int threadId;
   private String name;
   private int priority;

   public AdvancedThreadFactory(String name, int priority) {
      threadId = 1;
      this.name = name;
      this.priority = priority;
   }

   @Override
   public Thread newThread(Runnable r) {
      Thread t = new Thread(r, name + "-Thread_" + threadId);
      t.setPriority(priority);
      t.setDaemon(true);
      System.out.println("created new thread with id : " + threadId + " and name : " + t.getName());
      threadId++;
      return t;
   }
}

In the Main class, we've created an ExecutorService with a fixed thread pool of size 5 and our custom SimpleThreadFactory. We then submit 10 WorkerThread tasks to the executor. Each task simulates a delay of 5 seconds to mimic processing time.

Advanced Usage of ThreadFactory

Let's take a look at a more advanced ThreadFactory that sets the priority of the thread and also sets the threads as daemon threads.

import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;

public class Main {
   public static void main(String[] args) {
      AdvancedThreadFactory factory = new AdvancedThreadFactory("Test", Thread.NORM_PRIORITY);
      ExecutorService executor = Executors.newFixedThreadPool(5, factory);

      for (int i = 0; i < 10; i++) {
         Runnable worker = new WorkerThread("" + i);
         executor.execute(worker);
      }

      executor.shutdown();
      while (!executor.isTerminated()) {
      }

      System.out.println("All threads finished");
   }
}
class WorkerThread implements Runnable {
   private String command;

   public WorkerThread(String s) {
       this.command = s;
   }
   @Override
   public void run() {
      System.out.println(Thread.currentThread().getName() + " Start. Command = " + command);
      processCommand();
      System.out.println(Thread.currentThread().getName() + " End.");
   }
   private void processCommand() {
      try {
         Thread.sleep(5000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
   }
}

In this implementation, the AdvancedThreadFactory can create new threads with a given priority and as daemon threads.

Conclusion

Java's ThreadFactory interface is a powerful tool for creating and managing threads in a more refined way than just instantiating a Thread object. It's especially useful in complex multithreaded systems where greater control over threads is required. Remember, with the power of ThreadFactory, you can customize the thread's name, priority, daemon status, and more. This detailed level of control can significantly aid in debugging and managing your multithreaded applications.

Updated on: 19-Jun-2023

522 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements