Java ThreadPoolExecutor setThreadFactory() Method

The ThreadPoolExecutor class in Java provides the setThreadFactory() method to set a new ThreadFactory for creating new threads. This guide will cover the usage of the setThreadFactory() method, explain how it works, and provide concise examples to demonstrate its functionality in real-world use cases.

Introduction

The setThreadFactory() method is used to set a new ThreadFactory that the ThreadPoolExecutor will use to create new threads. A ThreadFactory is an interface that allows you to customize the creation of new threads, such as setting thread names, priorities, and daemon status.

setThreadFactory Method Syntax

The syntax for the setThreadFactory method is as follows:

public void setThreadFactory(ThreadFactory threadFactory)
  • The method takes a single parameter:
    • threadFactory - the new ThreadFactory to be used for creating new threads.

Examples

Example 1: Basic Usage of setThreadFactory()

In this example, we create a ThreadPoolExecutor, set a custom ThreadFactory, and submit tasks to the executor.

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

public class SetThreadFactoryExample {
    public static void main(String[] args) {
        // Create a custom thread factory
        ThreadFactory customThreadFactory = new ThreadFactory() {
            private final AtomicInteger threadNumber = new AtomicInteger(1);
            private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();

            @Override
            public Thread newThread(Runnable r) {
                Thread thread = defaultFactory.newThread(r);
                thread.setName("CustomThread-" + threadNumber.getAndIncrement());
                return thread;
            }
        };

        // Create a ThreadPoolExecutor with 2 threads
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);

        // Set the custom thread factory
        executor.setThreadFactory(customThreadFactory);

        // Submit tasks to the executor
        for (int i = 0; i < 3; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                System.out.println("Executing task " + taskNumber + " by " + Thread.currentThread().getName());
                try {
                    Thread.sleep(2000); // Simulate task execution
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskNumber + " completed by " + Thread.currentThread().getName());
            });
        }

        // Shutdown the executor
        executor.shutdown();
    }
}

Output:

Executing task 1 by CustomThread-1
Executing task 2 by CustomThread-2
Executing task 3 by CustomThread-1
Task 1 completed by CustomThread-1
Task 2 completed by CustomThread-2
Task 3 completed by CustomThread-1

Example 2: Customizing Thread Properties

In this example, we create a custom ThreadFactory to set specific properties for the threads, such as setting them as daemon threads.

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

public class CustomThreadPropertiesExample {
    public static void main(String[] args) {
        // Create a custom thread factory
        ThreadFactory customThreadFactory = new ThreadFactory() {
            private final AtomicInteger threadNumber = new AtomicInteger(1);
            private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();

            @Override
            public Thread newThread(Runnable r) {
                Thread thread = defaultFactory.newThread(r);
                thread.setName("DaemonThread-" + threadNumber.getAndIncrement());
                thread.setDaemon(true);
                return thread;
            }
        };

        // Create a ThreadPoolExecutor with 2 threads
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);

        // Set the custom thread factory
        executor.setThreadFactory(customThreadFactory);

        // Submit tasks to the executor
        for (int i = 0; i < 3; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                System.out.println("Executing task " + taskNumber + " by " + Thread.currentThread().getName() + " (daemon: " + Thread.currentThread().isDaemon() + ")");
                try {
                    Thread.sleep(2000); // Simulate task execution
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskNumber + " completed by " + Thread.currentThread().getName());
            });
        }

        // Shutdown the executor
        executor.shutdown();
    }
}

Output:

Executing task 1 by DaemonThread-1 (daemon: true)
Executing task 2 by DaemonThread-2 (daemon: true)
Executing task 3 by DaemonThread-1 (daemon: true)
Task 1 completed by DaemonThread-1
Task 2 completed by DaemonThread-2
Task 3 completed by DaemonThread-1

Example 3: Combining setThreadFactory() with Other Executor Methods

In this example, we use the setThreadFactory() method along with other executor methods to create a comprehensive task execution scenario.

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

public class ComprehensiveExample {
    public static void main(String[] args) {
        // Create a custom thread factory
        ThreadFactory customThreadFactory = new ThreadFactory() {
            private final AtomicInteger threadNumber = new AtomicInteger(1);
            private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();

            @Override
            public Thread newThread(Runnable r) {
                Thread thread = defaultFactory.newThread(r);
                thread.setName("WorkerThread-" + threadNumber.getAndIncrement());
                thread.setPriority(Thread.NORM_PRIORITY + 1);
                return thread;
            }
        };

        // Create a ThreadPoolExecutor with 4 threads
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(4);

        // Set the custom thread factory
        executor.setThreadFactory(customThreadFactory);

        // Submit tasks to the executor
        for (int i = 0; i < 5; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                System.out.println("Executing task " + taskNumber + " by " + Thread.currentThread().getName() + " (priority: " + Thread.currentThread().getPriority() + ")");
                try {
                    Thread.sleep(1000); // Simulate task execution
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskNumber + " completed by " + Thread.currentThread().getName());
            });
        }

        // Print the number of active threads
        System.out.println("Active threads: " + executor.getActiveCount());

        // Shutdown the executor
        executor.shutdown();
    }
}

Output:

Executing task 1 by WorkerThread-1 (priority: 6)
Executing task 2 by WorkerThread-2 (priority: 6)
Executing task 3 by WorkerThread-3 (priority: 6)
Executing task 4 by WorkerThread-4 (priority: 6)
Active threads: 4
Task 1 completed by WorkerThread-1
Executing task 5 by WorkerThread-1 (priority: 6)
Task 2 completed by WorkerThread-2
Task 3 completed by WorkerThread-3
Task 4 completed by WorkerThread-4
Task 5 completed by WorkerThread-1

Conclusion

The ThreadPoolExecutor.setThreadFactory() method in Java is used for setting a custom ThreadFactory to create new threads with specific properties. By using this method, you can customize thread creation, such as setting thread names, priorities, and daemon status, to meet the requirements of your application.

Comments