Using ThreadFactory in Java

Can someone briefly explain HOW AND WHEN to use ThreadFactory? An example with and without ThreadFactory can be really helpful in understanding the differences.

Thank!

+41
java multithreading concurrency
Jul 05 '10 at 13:13
source share
10 answers

The factory pattern is a creation pattern used in software development to encapsulate processes associated with creating objects.

Suppose we have some workflows for different tasks and they need special names (for example, for debugging purposes). Thus, we could implement ThreadFactory:

public class WorkerThreadFactory implements ThreadFactory { private int counter = 0; private String prefix = ""; public WorkerThreadFactory(String prefix) { this.prefix = prefix; } public Thread newThread(Runnable r) { return new Thread(r, prefix + "-" + counter++); } } 

If you had such a requirement, it would be quite difficult to implement it without a factory template or builder.




ThreadFactory is part of the Java API because it is also used by other classes. So the above example shows why we should use 'a factory to create threads in some cases, but of course there is absolutely no need to implement java.util.concurrent.ThreadFactory to complete this task.

+36
Jul 05 '10 at 13:37
source share
— -

Here is one possible use. If you have an executing service that executes your running tasks in a multi-threaded way, and from time to time your thread dies from an uncaught exception. Suppose you do not register all of these exceptions. ThreadFactory solves this problem:

 ExecutorService executor = Executors.newSingleThreadExecutor(new LoggingThreadFactory()); executor.submit(new Runnable() { @Override public void run() { someObject.someMethodThatThrowsRuntimeException(); } }); 

LoggingThreadFactory can be implemented as follows:

 public class LoggingThreadFactory implements ThreadFactory { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { LoggerFactory.getLogger(t.getName()).error(e.getMessage(), e); } }); return t; } } 
+53
Jul 05 2018-10-05T00:
source share

Some internal operations

The topic is pretty well covered, with the exception of some internal works that are not so easy to see. When creating a w / stream, the constructor of the newly created stream inherits the current threads:

  • ThreadGroup (if not specified, or System.getSecurityManager (). GetThreadGroup () returns an arbitrary ThreadGroup). In some cases, a thread group in its own right may be important and may lead to incorrect termination / termination of a thread. ThreadGroup will act as the default exception handler.
  • ContextClassLoader - in a managed environment, which should not be a big problem, since the environment should switch CCL, but if you must implement this, do not forget. The leak of the calling CCL is pretty bad, as well as the thread group (especially if threadGroup is a subclass rather than a direct java.lang.ThreadGroup - you must override ThreadGroup.uncaughtException)
  • AccessControlContext - there is practically nothing to do here (except for launching in a dedicated thread), since the field is intended for internal use only, and few even suspect the existence.
  • stack size (usually not specified, but it can be used to get a stream with a very narrow stack size based on the caller)
  • priority - most people know and tend to install it (more or less)
  • daemon status - this is usually not very important and easily noticeable (if the application just disappears)
  • Finally: the thread inherits the caller InheritableThreadLocal - which may (or may not) lead to some consequences. Again nothing can be done except that it spawns a stream into a dedicated stream.

Depending on the application, the above points may not have any effect at all, but in some cases some of them can lead to class / resource leaks that are difficult to detect and exhibit non-deterministic behavior.




This will make an extra long post, but so ...

Below is some (hopefully) reusable code for implementing ThreadFactory , it can be used in managed environments to ensure the correct ThreadGroup (which can limit priority or interrupt threads), ContextClassLoader, stack, etc. set (and / or can be customized) and do not leak. If there is any interest, I can show how to handle inherited ThreadLocals or inherited acc (which can essentially be missed by the calling classloader)

 package bestsss.util; import java.lang.Thread.UncaughtExceptionHandler; import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicLong; public class ThreadFactoryX implements ThreadFactory{ //thread properties long stackSize; String pattern; ClassLoader ccl; ThreadGroup group; int priority; UncaughtExceptionHandler exceptionHandler; boolean daemon; private boolean configured; private boolean wrapRunnable;//if acc is present wrap or keep it protected final AccessControlContext acc; //thread creation counter protected final AtomicLong counter = new AtomicLong(); public ThreadFactoryX(){ final Thread t = Thread.currentThread(); ClassLoader loader; AccessControlContext acc = null; try{ loader = t.getContextClassLoader(); if (System.getSecurityManager()!=null){ acc = AccessController.getContext();//keep current permissions acc.checkPermission(new RuntimePermission("setContextClassLoader")); } }catch(SecurityException _skip){ //no permission loader =null; acc = null; } this.ccl = loader; this.acc = acc; this.priority = t.getPriority(); this.daemon = true;//Executors have it false by default this.wrapRunnable = true;//by default wrap if acc is present (+SecurityManager) //default pattern - caller className StackTraceElement[] stack = new Exception().getStackTrace(); pattern(stack.length>1?getOuterClassName(stack[1].getClassName()):"ThreadFactoryX", true); } public ThreadFactory finishConfig(){ configured = true; counter.addAndGet(0);//write fence "w/o" volatile return this; } public long getCreatedThreadsCount(){ return counter.get(); } protected void assertConfigurable(){ if (configured) throw new IllegalStateException("already configured"); } private static String getOuterClassName(String className){ int idx = className.lastIndexOf('.')+1; className = className.substring(idx);//remove package idx = className.indexOf('$'); if (idx<=0){ return className;//handle classes starting w/ $ } return className.substring(0,idx);//assume inner class } @Override public Thread newThread(Runnable r) { configured = true; final Thread t = new Thread(group, wrapRunnable(r), composeName(r), stackSize); t.setPriority(priority); t.setDaemon(daemon); t.setUncaughtExceptionHandler(exceptionHandler);//securityException only if in the main group, shall be safe here //funny moment Thread.getUncaughtExceptionHandler() has a race.. badz (can throw NPE) applyCCL(t); return t; } private void applyCCL(final Thread t) { if (ccl!=null){//use factory creator ACC for setContextClassLoader AccessController.doPrivileged(new PrivilegedAction<Object>(){ @Override public Object run() { t.setContextClassLoader(ccl); return null; } }, acc); } } private Runnable wrapRunnable(final Runnable r){ if (acc==null || !wrapRunnable){ return r; } Runnable result = new Runnable(){ public void run(){ AccessController.doPrivileged(new PrivilegedAction<Object>(){ @Override public Object run() { r.run(); return null; } }, acc); } }; return result; } protected String composeName(Runnable r) { return String.format(pattern, counter.incrementAndGet(), System.currentTimeMillis()); } //standard setters allowing chaining, feel free to add normal setXXX public ThreadFactoryX pattern(String patten, boolean appendFormat){ assertConfigurable(); if (appendFormat){ patten+=": %d @ %tF %<tT";//counter + creation time } this.pattern = patten; return this; } public ThreadFactoryX daemon(boolean daemon){ assertConfigurable(); this.daemon = daemon; return this; } public ThreadFactoryX priority(int priority){ assertConfigurable(); if (priority<Thread.MIN_PRIORITY || priority>Thread.MAX_PRIORITY){//check before actual creation throw new IllegalArgumentException("priority: "+priority); } this.priority = priority; return this; } public ThreadFactoryX stackSize(long stackSize){ assertConfigurable(); this.stackSize = stackSize; return this; } public ThreadFactoryX threadGroup(ThreadGroup group){ assertConfigurable(); this.group= group; return this; } public ThreadFactoryX exceptionHandler(UncaughtExceptionHandler exceptionHandler){ assertConfigurable(); this.exceptionHandler= exceptionHandler; return this; } public ThreadFactoryX wrapRunnable(boolean wrapRunnable){ assertConfigurable(); this.wrapRunnable= wrapRunnable; return this; } public ThreadFactoryX ccl(ClassLoader ccl){ assertConfigurable(); this.ccl = ccl; return this; } } 

Also very simple use:

 ThreadFactory factory = new TreadFactoryX().priority(3).stackSize(0).wrapRunnable(false).pattern("Socket workers", true). daemon(false).finishConfig(); 
+14
Jan 19 2018-11-11T00:
source share

IMHO, the single most important function of ThreadFactory is to name threads something useful. Having threads in stacktrace named pool-1-thread-2 or worse Thread-12 is a complete pain in diagnosing problems.

Of course, the presence of ThreadGroup , the status and priority of the daemon are also useful.

+3
Jul 06 2018-10-06T00:
source share

As mentioned in "InsertNickHere", you will need to understand the Factory Pattern .

A good example of using ThreadFactory is ThreadPoolExecutor : An artist will create threads, if necessary, and take care of the union. If you want to enter the creation process and provide special names to the created threads or assign them to ThreadGroup, you can create a ThreadFactory for this purpose and pass it to the Executor.

A bit of IoC style.

+2
Jul 05 '10 at 13:51
source share

It is always useful to use a custom factory thread. The plants by default are not very useful. You should use a custom factory for the following reasons:

  • To have custom thread names
  • Select stream types
  • Stream Priority Selection
  • To handle uncaught exceptions

Check this post: http://wilddiary.com/understanding-java-threadfactory-creating-custom-thread-factories/

+2
Sep 12 '14 at 10:55
source share

ThreadFactory is a single-method interface public abstract java.lang.Thread newThread(java.lang.Runnable arg0);

Its use depends on your requirement. Suppose you want certain functionality to always create Daemon threads. You can easily achieve this with ThreadFactory.

The following code is intended only to talk about the fundamental. It does not perform any specific functions.

 package TestClasses; import java.util.concurrent.ThreadFactory; public class ThreadFactoryEx implements ThreadFactory{ @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setDaemon(true); return t; } } package TestClasses; import java.util.concurrent.ThreadPoolExecutor; public class RunnableEx implements Runnable{ @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 5; i++) { System.out.println("in a loop" + i + "times"); } } } package TestClasses; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Thread1 { public static void main(String[] args) { ExecutorService exe = Executors.newCachedThreadPool(new ThreadFactoryEx()); for (int i = 0; i < 4; i++) { exe.execute(new RunnableEx()); } } } 
+1
Jan 25 '15 at 6:09
source share

Using ThreadFactory in Java

An object that creates new threads on demand. Using thread factories removes hard calls to new Thread , allowing applications to use special thread subclasses, priorities, etc.

The simplest implementation of this interface is:

 class SimpleThreadFactory implements ThreadFactory { public Thread newThread(Runnable r) { return new Thread(r); } } 

DefaultThreadFactory ThreadPoolExecutor.java

 static class DefaultThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber = new AtomicInteger(1); private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (t.isDaemon()) t.setDaemon(false); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } } 

Source

+1
Jan 16 '16 at 6:00
source share

Check out VerboseThreads (implements ThreadFactory ) from jcabi-log . This implementation makes Thread that exception logs when they are thrown from them. A very useful class when you need to see when and why your threads die.

0
Jan 02
source share

ThreadFactory will be useful

  • to set a more descriptive stream name
  • to set the thread daemon status
  • to set thread priority

You can use ThreadFactoryBuilder from google guava lib to create ThreadFactory , like this

 ThreadFactory threadFactory = new ThreadFactoryBuilder() .setNameFormat("MyThreadPool-Worker-%d") .setDaemon(true) .build(); 
0
Aug 10 '17 at 2:16 on
source share



All Articles