Why do we need to specify meaningful thread names when creating threads or thread pools?

The ultimate goal is to facilitate backtracking.

In our daily development, many thread pools are created for resource isolation in a project, but if we don’t have a good name, it can be difficult to locate problems when they occur.

public class Demo5 { public static void main( String[] args ) throws IOException { new Thread(()->{ System.out.println(" Save user information.........." ); try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } throw new NullPointerException(); }).start(); System.in.read(); }}Copy the code

The above code is to start a thread to save user information, and then throw an exception!

The following error message is displayed:

From the analysis of the run error, thread0 threw a null pointer, so it is impossible to determine the exception thrown by the user module Thread from the log alone. Let’s first analyze where Thread-0 came from.

Let’s take a look at the code that creates the thread:

public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
  private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }Copy the code

As you can see from the code above, if we do not specify a Thread name, we will automatically create a Thread name of “Thread-“+nextThreadNum() as the default name for the Thread.

If there are multiple business modules in a system, such as the user module, the order module, the shopping cart module, and so on, all using their own thread pool without specifying a name, the exception thrown will be impossible to determine which module is faulty unless it is related to business content.

You also need to specify the name of the thread pool when creating it

We can use threadFactory to specify the name of the thread:

(1) You can use the thread factory to give each created thread a more meaningful name. The thread pool is named by adding a group prefix to the factory. When the virtual machine stack is analyzed, it is possible to know which thread factory the thread tasks are generated by.

(2) Use Guava to set the thread name

new ThreadFactoryBuilder().setNameFormat(“XX-task-%d”).build();

(3) Custom implementation: ThreadFactory

Executors Specifies the default threadFactory thread name in the static factory. The thread name is Pool-digital-thread-digital.

Let’s look at thread pools:

public class Demo6 { public static void main( String[] args ) throws IOException { ThreadPoolExecutor executorOne = new ThreadPoolExecutor(5, 5, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>()); Executorone. execute(()->{system.out.println (" save user information "); throw new NullPointerException(); }); System.in.read(); }}Copy the code

Results:

The thread pool is pool-1-thread-1. The thread pool is pool-1-thread-1.

Let’s look at the source code for ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          RejectedExecutionHandler handler
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), handler);
}Copy the code
 public static ThreadFactory defaultThreadFactory() {
        return new DefaultThreadFactory();
    }Copy the code
DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s ! = null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } ``` ``` private static final AtomicInteger poolNumber = new AtomicInteger(1);Copy the code

So how do we define a ThreadFactory?

public class NamedThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber = new AtomicInteger(1); private final AtomicInteger threadNumber = new AtomicInteger(1); private String namePrefix; private final ThreadGroup group; public NamedThreadFactory( String name ) { this.namePrefix = namePrefix = name + "-" + poolNumber.getAndIncrement() + "-thread-"; SecurityManager s = System.getSecurityManager(); group = (s ! = null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); } @Override 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; }}Copy the code
public class Demo6 { public static void main( String[] args ) throws IOException { ThreadPoolExecutor executorOne = new ThreadPoolExecutor(5, 5, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(),new NamedThreadFactory("UserModule")); Executorone. execute(()->{system.out.println (" save user information "); throw new NullPointerException(); }); System.in.read(); }}Copy the code

Results:

We see that from the thread name in the error stack, we can locate which module has the error.

conclusion

Specify meaningful thread names when creating threads or thread pools to facilitate backtracking in case of errors.

Custom thread factories, and group by external characteristics, such as calls from the same machine room, assigning machine room numbers to

Wenyuan network, only for the use of learning, such as infringement, contact deletion.

I’ve compiled the interview questions and answers in PDF files, as well as a set of learning materials covering, but not limited to, the Java Virtual Machine, the Spring framework, Java threads, data structures, design patterns and more.

Follow the public account “Java Circle” for information, as well as quality articles delivered daily.