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, a project will create many thread pools for resource isolation, but if we do not have a good name, it will be difficult to locate when there is a problem.
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(); } }
The above code is to start a thread to save user information, and then throw an exception!
The error message is as follows:
It can be analyzed from the running error that Thread-0 throws a null pointer, so it is impossible to judge the exception thrown by the user module thread from this log alone. Let's first analyze how Thread-0 came from.
Let's look at the code to create a thread:
public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); } private static int threadInitNumber; private static synchronized int nextThreadNum() { return threadInitNumber++; }
From the above code, if we do not specify a thread name, we will automatically create the thread name "Thread-"+nextThreadNum() as the default name of the thread.
If there are multiple business modules in a system, such as user module, order module, shopping cart module, etc., all use their own thread pool without specifying the name, the exception thrown cannot be judged at all unless it is related to the business content.
When creating a thread pool, you also need to specify the name of the thread pool
We can use threadFactory to specify the name of the thread:
(1) Each created thread can be given a more meaningful name through the thread factory. The thread pool is named by adding a group prefix to the factory. When analyzing the virtual machine stack, you can know which thread factory the thread task is generated by.
(2) Using Guava to set the thread name
new ThreadFactoryBuilder().setNameFormat("XX-task-%d").build();
(3) Custom implementation: ThreadFactory
The default threadFactory in Executors static factory. The naming rule of thread is "pool number thread number".
Let's see offline Chengchi:
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(); } }
result:
The name of the print thread pool we see is pool-1-thread-1, so how?
Let's take a look at the source code of 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); }
public static ThreadFactory defaultThreadFactory() { return new DefaultThreadFactory(); }
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);
How do we define 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; } }
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(); } }
result:
We see that from the thread name in the error stack, we can locate which module has an error.
summary
When creating a thread or thread pool, please specify a meaningful thread name to facilitate backtracking when an error occurs.
Customize thread factory and group according to external characteristics, for example, call from the same machine room, assign machine room number to
Source network, only for learning, if there is infringement, contact delete.
I have compiled the interview questions and answers into PDF documents, as well as a set of learning materials, including Java virtual machine, spring framework, java thread, data structure, design pattern, etc., but not limited to this.
Focus on the official account [java circle] for information, as well as daily delivery of quality articles.