Saturday 4 November 2023

Customizing Thread Creation with ThreadFactory

ThreadFactory is a Functional interface that provides a convenient a way to create new threads on demand. ThreadFactory is used to decouple the process of thread creation from the rest of your application's logic.

Definition of ThreadFactory interface

public interface ThreadFactory {

    Thread newThread(Runnable r);
}

 

The newThread method takes a Runnable object as a parameter and returns a new Thread object.

 

For example, following CustomThreaFactory class generate thread with priority 7.

 


CustomThreadFactory.java
package com.sample.app.threads;

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

public class CustomThreadFactory implements ThreadFactory{
	private int threadCount = 1;
	
	@Override
	public Thread newThread(Runnable runnable) {
		Thread thread = Executors.defaultThreadFactory().newThread(runnable);
        thread.setName("MyThread-" + threadCount++);
        thread.setPriority(7);
        return thread;
	}

}

 

‘CustomThreadFactoryDemo’ use CustomThreadFactory to create new threads for you.

 

CustomThreadFactoryDemo.java

 

package com.sample.app;

import java.util.Random;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import com.sample.app.threads.CustomThreadFactory;

public class CustomThreadFactoryDemo {
	
	public static void main(String[] args) {
		Runnable runnable = () -> {
			System.out.println(Thread.currentThread().getName() + " executing this code");
			sleepRandomSeconds(5);
			System.out.println(Thread.currentThread().getName() + " finished executing this code");
			
		};
		
		ThreadFactory threadFactory = new CustomThreadFactory();
		
		for(int i = 0; i<10; i++) {
			threadFactory.newThread(runnable).start();
		}
		
	}
	
	private static void sleepRandomSeconds(int upperBound) {
		try {
			TimeUnit.SECONDS.sleep(new Random().nextInt(upperBound));
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

 

Sample Output

MyThread-1 executing this code
MyThread-2 executing this code
MyThread-3 executing this code
MyThread-4 executing this code
MyThread-5 executing this code
MyThread-6 executing this code
MyThread-7 executing this code
MyThread-8 executing this code
MyThread-9 executing this code
MyThread-10 executing this code
MyThread-10 finished executing this code
MyThread-1 finished executing this code
MyThread-4 finished executing this code
MyThread-3 finished executing this code
MyThread-7 finished executing this code
MyThread-2 finished executing this code
MyThread-5 finished executing this code
MyThread-6 finished executing this code
MyThread-8 finished executing this code
MyThread-9 finished executing this code

 

In this example, CustomThreadFactory implements the ThreadFactory interface and overrides the newThread method. It uses the defaultThreadFactory() method from Executors to create the underlying Thread object and then customizes the thread's name by appending a count to it, and set the priority to 7.

 

Using Custom Thread factory, we can customize the thread creation in number of ways, for example, we can

 

a.   Set the thread name prefix

b.   Set the thread priority

c.    Set the thread daemon status

d.   Set the thread stack size

e.   Set the thread security context

f.     Create threads from a specific thread group

 

Let’s improvise CustomThreadFactory by passing the thread priority as argument.

 

CustomThreadFactory.java

 

package com.sample.app.threads;

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

public class CustomThreadFactory implements ThreadFactory{
	private static final AtomicInteger THREAD_COUNT = new AtomicInteger();
	private int priority;
	
	public CustomThreadFactory(int priority) {
		this.priority = priority;
	}
	
	@Override
	public Thread newThread(Runnable runnable) {
		Thread thread = Executors.defaultThreadFactory().newThread(runnable);
        thread.setName("MyThread-" + THREAD_COUNT.incrementAndGet());
        thread.setPriority(priority);
        return thread;
	}

}

Use ThredFactory in ThreadPool consruction

ThreadPoolExecutor executorService = new ThreadPoolExecutor(10, 20, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new CustomThreadFactory(7));

 

The executor service will now use the CustomThreadFactory to create new threads as needed. All of the new threads will have the name prefix "MyThread-" and the thread priority 7.

 

Find the below working application.

 

ThreadPoolDemo.java

package com.sample.app;

import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.sample.app.threads.CustomThreadFactory;

public class ThreadPoolDemo {

	private static void sleepRandomSeconds(int upperBound) {
		try {
			TimeUnit.SECONDS.sleep(new Random().nextInt(upperBound));
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		ThreadPoolExecutor executorService = new ThreadPoolExecutor(10, 20, 0L, TimeUnit.MILLISECONDS,
				new LinkedBlockingQueue<>(), new CustomThreadFactory(7));

		Runnable runnable = () -> {
			System.out.println(Thread.currentThread().getName() + " executing this code");
			sleepRandomSeconds(5);
			System.out.println(Thread.currentThread().getName() + " finished executing this code");

		};
		
		for(int i=0; i < 10; i++) {
			executorService.submit(runnable);
		}
		
		executorService.shutdown();

	}

}

Sample Output

MyThread-1 executing this code
MyThread-3 executing this code
MyThread-2 executing this code
MyThread-4 executing this code
MyThread-5 executing this code
MyThread-3 finished executing this code
MyThread-6 executing this code
MyThread-7 executing this code
MyThread-8 executing this code
MyThread-9 executing this code
MyThread-10 executing this code
MyThread-10 finished executing this code
MyThread-9 finished executing this code
MyThread-4 finished executing this code
MyThread-7 finished executing this code
MyThread-6 finished executing this code
MyThread-2 finished executing this code
MyThread-1 finished executing this code
MyThread-8 finished executing this code
MyThread-5 finished executing this code



Previous                                                    Next                                                    Home

No comments:

Post a Comment