ExecutorService 的线程和线程池命名

发布于 2024-11-09 07:42:11 字数 373 浏览 6 评论 0 原文

假设我有一个使用 Executor 框架的应用程序,

Executors.newSingleThreadExecutor().submit(new Runnable(){
    @Override
    public void run(){
        // do stuff
    }
}

当我在调试器中运行此应用程序时,会创建一个具有以下(默认)名称的线程:Thread[pool-1-线程1]。正如您所看到的,这并不是很有用,而且据我所知,Executor 框架没有提供一种简单的方法来命名创建的线程或线程池。

那么,如何为线程/线程池提供名称呢?例如,Thread[FooPool-FooThread]

Let's say I have an application that utilizes the Executor framework as such

Executors.newSingleThreadExecutor().submit(new Runnable(){
    @Override
    public void run(){
        // do stuff
    }
}

When I run this application in the debugger, a thread is created with the following (default) name: Thread[pool-1-thread-1]. As you can see, this isn't terribly useful and as far as I can tell, the Executor framework does not provide an easy way to name the created threads or thread-pools.

So, how does one go about providing names for the threads/thread-pools? For instance, Thread[FooPool-FooThread].

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(21

七秒鱼° 2024-11-16 07:42:11

Guava 几乎总有您想要的需要

ThreadFactory namedThreadFactory = 
  new ThreadFactoryBuilder().setNameFormat("my-sad-thread-%d").build()

并将其传递给您的ExecutorService。

Guava almost always has what you need.

ThreadFactory namedThreadFactory = 
  new ThreadFactoryBuilder().setNameFormat("my-sad-thread-%d").build()

and pass it off to your ExecutorService.

葵雨 2024-11-16 07:42:11

您可以提供 ThreadFactorynewSingleThreadScheduledExecutor(ThreadFactory threadFactory)。工厂将负责创建线程,并能够命名它们。

引用 Javadoc

创建新线程

新线程是使用ThreadFactory创建的。如果没有另外指定,则使用 Executors.defaultThreadFactory(),它创建的线程都位于同一个 ThreadGroup 中,并具有相同的 NORM_PRIORITY优先级和非守护进程状态。通过提供不同的 ThreadFactory,您可以更改线程的名称、线程组、优先级、守护进程状态等。如果 ThreadFactory 无法创建线程,则返回 null从 newThread 开始,执行器将继续,但可能无法执行任何任务

You could supply a ThreadFactory to newSingleThreadScheduledExecutor(ThreadFactory threadFactory). The factory will be responsibe for creating threads, and will be able to name them.

To quote the Javadoc:

Creating new threads

New threads are created using a ThreadFactory. If not otherwise specified, a Executors.defaultThreadFactory() is used, that creates threads to all be in the same ThreadGroup and with the same NORM_PRIORITY priority and non-daemon status. By supplying a different ThreadFactory, you can alter the thread's name, thread group, priority, daemon status, etc. If a ThreadFactory fails to create a thread when asked by returning null from newThread, the executor will continue, but might not be able to execute any tasks

落墨 2024-11-16 07:42:11

您可以尝试提供自己的线程工厂,它将创建具有适当名称的线程。这是一个例子:

class YourThreadFactory implements ThreadFactory {
   public Thread newThread(Runnable r) {
     return new Thread(r, "Your name");
   }
 }

Executors.newSingleThreadExecutor(new YourThreadFactory()).submit(someRunnable);

或者在 Kotlin 中

Executors.newSingleThreadExecutor { r -> Thread(r, "Your name") }

You can try to provide your own thread factory, which will create thread with appropriate names. Here's one example:

class YourThreadFactory implements ThreadFactory {
   public Thread newThread(Runnable r) {
     return new Thread(r, "Your name");
   }
 }

Executors.newSingleThreadExecutor(new YourThreadFactory()).submit(someRunnable);

Or in Kotlin

Executors.newSingleThreadExecutor { r -> Thread(r, "Your name") }
凹づ凸ル 2024-11-16 07:42:11

您还可以在执行线程时更改线程的名称:

Thread.currentThread().setName("FooName");

例如,如果您对不同类型的任务使用相同的 ThreadFactory,这可能会很有趣。

You can also change the name of your thread afterwards, while the thread is executed:

Thread.currentThread().setName("FooName");

That could be of interest if for instance you're using the same ThreadFactory for different type of tasks.

忘东忘西忘不掉你 2024-11-16 07:42:11

BasicThreadFactory 对于提供命名行为也很有用。您可以使用 Builder 根据需要命名线程,而不是编写匿名内部类。这是 javadoc 中的示例:

 // Create a factory that produces daemon threads with a naming pattern and
 // a priority
 BasicThreadFactory factory = new BasicThreadFactory.Builder()
     .namingPattern("workerthread-%d")
     .daemon(true)
     .priority(Thread.MAX_PRIORITY)
     .build();
 // Create an executor service for single-threaded execution
 ExecutorService exec = Executors.newSingleThreadExecutor(factory);

The BasicThreadFactory from apache commons-lang is also useful to provide the naming behavior. Instead of writing an anonymous inner class, you can use the Builder to name the threads as you want. Here's the example from the javadocs:

 // Create a factory that produces daemon threads with a naming pattern and
 // a priority
 BasicThreadFactory factory = new BasicThreadFactory.Builder()
     .namingPattern("workerthread-%d")
     .daemon(true)
     .priority(Thread.MAX_PRIORITY)
     .build();
 // Create an executor service for single-threaded execution
 ExecutorService exec = Executors.newSingleThreadExecutor(factory);
菊凝晚露 2024-11-16 07:42:11

如果您使用 Spring,则有 CustomizedThreadFactory,您可以为其设置线程名称前缀。

示例:

ExecutorService alphaExecutor =
    Executors.newFixedThreadPool(10, new CustomizableThreadFactory("alpha-"));

或者,您可以使用 ThreadPoolExecutorFactoryBean - 那么线程都将以 beanName- 前缀命名。

@Bean
public ThreadPoolExecutorFactoryBean myExecutor() {
    ThreadPoolExecutorFactoryBean executorFactoryBean = new ThreadPoolExecutorFactoryBean();
    // configuration of your choice
    return executorFactoryBean;
}

在上面的示例中,线程将以 myExecutor- 前缀命名。您可以通过在工厂 bean 上设置 executorFactoryBean.setThreadNamePrefix("myPool-") 来将前缀显式设置为不同的值(例如 "myPool-")。

If you are using Spring, there is CustomizableThreadFactory for which you can set a thread name prefix.

Example:

ExecutorService alphaExecutor =
    Executors.newFixedThreadPool(10, new CustomizableThreadFactory("alpha-"));

Alternatively, you can create your ExecutorService as a Spring bean using ThreadPoolExecutorFactoryBean - then the threads will all be named with the beanName- prefix.

@Bean
public ThreadPoolExecutorFactoryBean myExecutor() {
    ThreadPoolExecutorFactoryBean executorFactoryBean = new ThreadPoolExecutorFactoryBean();
    // configuration of your choice
    return executorFactoryBean;
}

In the example above, the threads will be named with myExecutor- prefix. You can set the prefix explicitly to a different value (eg. "myPool-") by setting executorFactoryBean.setThreadNamePrefix("myPool-") on the factory bean.

可遇━不可求 2024-11-16 07:42:11

Oracle 有一个开放 RFE。从 Oracle 员工的评论来看,他们似乎不理解这个问题,也不会解决。这是 JDK 中支持非常简单的事情之一(不会破坏向后兼容性),因此 RFE 被误解是一种耻辱。

正如所指出的,您需要实现自己的 ThreadFactory< /a>.如果您不想仅出于此目的引入 Guava 或 Apache Commons,我在这里提供了您可以使用的 ThreadFactory 实现。它与您从 JDK 获得的内容完全相同,除了能够将线程名称前缀设置为“pool”之外的其他内容。

package org.demo.concurrency;

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

/**
 * ThreadFactory with the ability to set the thread name prefix. 
 * This class is exactly similar to 
 * {@link java.util.concurrent.Executors#defaultThreadFactory()}
 * from JDK8, except for the thread naming feature.
 *
 * <p>
 * The factory creates threads that have names on the form
 * <i>prefix-N-thread-M</i>, where <i>prefix</i>
 * is a string provided in the constructor, <i>N</i> is the sequence number of
 * this factory, and <i>M</i> is the sequence number of the thread created 
 * by this factory.
 */
public class ThreadFactoryWithNamePrefix implements ThreadFactory {

    // Note:  The source code for this class was based entirely on 
    // Executors.DefaultThreadFactory class from the JDK8 source.
    // The only change made is the ability to configure the thread
    // name prefix.


    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    /**
     * Creates a new ThreadFactory where threads are created with a name prefix
     * of <code>prefix</code>.
     *
     * @param prefix Thread name prefix. Never use a value of "pool" as in that
     *      case you might as well have used
     *      {@link java.util.concurrent.Executors#defaultThreadFactory()}.
     */
    public ThreadFactoryWithNamePrefix(String prefix) {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup()
                : Thread.currentThread().getThreadGroup();
        namePrefix = prefix + "-"
                + poolNumber.getAndIncrement()
                + "-thread-";
    }


    @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;
    }
}

当您想使用它时,您只需利用所有 Executors 方法都允许您提供自己的 ThreadFactory 的事实。

    Executors.newSingleThreadExecutor();

将提供一个 ExecutorService,其中线程名为 pool-N-thread-M,但通过使用,

    Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("primecalc"));

您将获得一个 ExecutorService,其中线程名为 primecalc-N-thread-M 。瞧!

There's an open RFE for this with Oracle. From the comments from the Oracle employee it seems they don't understand the issue and won't fix. It's one of these things that is dead simple to support in the JDK (without breaking backwards compatibility) so it is kind of a shame that the RFE gets misunderstood.

As pointed out you need to implement your own ThreadFactory. If you don't want to pull in Guava or Apache Commons just for this purpose I provide here a ThreadFactory implementation that you can use. It is exactly similar to what you get from the JDK except for the ability to set the thread name prefix to something else than "pool".

package org.demo.concurrency;

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

/**
 * ThreadFactory with the ability to set the thread name prefix. 
 * This class is exactly similar to 
 * {@link java.util.concurrent.Executors#defaultThreadFactory()}
 * from JDK8, except for the thread naming feature.
 *
 * <p>
 * The factory creates threads that have names on the form
 * <i>prefix-N-thread-M</i>, where <i>prefix</i>
 * is a string provided in the constructor, <i>N</i> is the sequence number of
 * this factory, and <i>M</i> is the sequence number of the thread created 
 * by this factory.
 */
public class ThreadFactoryWithNamePrefix implements ThreadFactory {

    // Note:  The source code for this class was based entirely on 
    // Executors.DefaultThreadFactory class from the JDK8 source.
    // The only change made is the ability to configure the thread
    // name prefix.


    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    /**
     * Creates a new ThreadFactory where threads are created with a name prefix
     * of <code>prefix</code>.
     *
     * @param prefix Thread name prefix. Never use a value of "pool" as in that
     *      case you might as well have used
     *      {@link java.util.concurrent.Executors#defaultThreadFactory()}.
     */
    public ThreadFactoryWithNamePrefix(String prefix) {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup()
                : Thread.currentThread().getThreadGroup();
        namePrefix = prefix + "-"
                + poolNumber.getAndIncrement()
                + "-thread-";
    }


    @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;
    }
}

When you want to use it you simply take advantage of the fact that all Executors methods allow you to provide your own ThreadFactory.

This

    Executors.newSingleThreadExecutor();

will give an ExecutorService where threads are named pool-N-thread-M but by using

    Executors.newSingleThreadExecutor(new ThreadFactoryWithNamePrefix("primecalc"));

you'll get an ExecutorService where threads are named primecalc-N-thread-M. Voila!

别闹i 2024-11-16 07:42:11

正如其他答案已经说过的,您可以创建并使用您自己的 java.util.concurrent.ThreadFactory 接口的实现(不需要外部库)。
我将代码粘贴在下面,因为它与以前的答案不同,因为它使用 String.format 方法并采用线程的基本名称作为构造函数参数:

import java.util.concurrent.ThreadFactory;

public class NameableThreadFactory implements ThreadFactory{
    private int threadsNum;
    private final String namePattern;

    public NameableThreadFactory(String baseName){
        namePattern = baseName + "-%d";
    }

    @Override
    public Thread newThread(Runnable runnable){
        threadsNum++;
        return new Thread(runnable, String.format(namePattern, threadsNum));
    }    
}

这是一个用法示例:

ThreadFactory  threadFactory = new NameableThreadFactory("listenerThread");        
final ExecutorService executorService = Executors.newFixedThreadPool(5, threadFactory);

编辑:使我的ThreadFactory实现线程安全,感谢@mchernyakov指出这一点。
尽管 ThreadFactory 文档中没有任何地方说它的实现必须是线程安全的,但 DefaultThreadFactory 是线程安全的事实是一个很大的暗示:

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

public class NameableThreadFactory implements ThreadFactory{
    private final AtomicInteger threadsNum = new AtomicInteger();

    private final String namePattern;

    public NameableThreadFactory(String baseName){
        namePattern = baseName + "-%d";
    }

    @Override
    public Thread newThread(Runnable runnable){
        return new Thread(runnable, String.format(namePattern, threadsNum.addAndGet(1)));
    }    
}

As other answers already said, you may create and use your own implementation of the java.util.concurrent.ThreadFactory interface (no external libraries required).
I am pasting my code below because it is different than previous answers since it uses String.format method and takes a base name for the threads as a constructor argument:

import java.util.concurrent.ThreadFactory;

public class NameableThreadFactory implements ThreadFactory{
    private int threadsNum;
    private final String namePattern;

    public NameableThreadFactory(String baseName){
        namePattern = baseName + "-%d";
    }

    @Override
    public Thread newThread(Runnable runnable){
        threadsNum++;
        return new Thread(runnable, String.format(namePattern, threadsNum));
    }    
}

And this is an example of usage:

ThreadFactory  threadFactory = new NameableThreadFactory("listenerThread");        
final ExecutorService executorService = Executors.newFixedThreadPool(5, threadFactory);

EDIT: making my ThreadFactory implementation thread-safe, thanks to @mchernyakov for pointing it out.
Even though nowhere in the ThreadFactory documentation is said that its implementations must be thread-safe, the fact that the DefaultThreadFactory is thread-safe is a big hint:

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

public class NameableThreadFactory implements ThreadFactory{
    private final AtomicInteger threadsNum = new AtomicInteger();

    private final String namePattern;

    public NameableThreadFactory(String baseName){
        namePattern = baseName + "-%d";
    }

    @Override
    public Thread newThread(Runnable runnable){
        return new Thread(runnable, String.format(namePattern, threadsNum.addAndGet(1)));
    }    
}
盗梦空间 2024-11-16 07:42:11

我发现如果您只想更改单个线程执行器的名称,那么使用 lambda 作为线程工厂是最简单的。

Executors.newSingleThreadExecutor(runnable -> new Thread(runnable, "Your name"));

I find it easiest to use a lambda as a thread factory if you just want to change the name for a single thread executor.

Executors.newSingleThreadExecutor(runnable -> new Thread(runnable, "Your name"));
毁梦 2024-11-16 07:42:11

一种快速但肮脏的方法是在 run() 方法中使用 Thread.currentThread().setName(myName);

A quick and dirty way is to use Thread.currentThread().setName(myName); in the run() method.

[旋木] 2024-11-16 07:42:11
private class TaskThreadFactory implements ThreadFactory
{

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r, "TASK_EXECUTION_THREAD");

        return t;
    }

}

将 ThreadFactory 传递给执行服务,然后就可以开始了

private class TaskThreadFactory implements ThreadFactory
{

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r, "TASK_EXECUTION_THREAD");

        return t;
    }

}

Pass the ThreadFactory to an executorservice and you are good to go

生生漫 2024-11-16 07:42:11

扩展 ThreadFactory

公共接口ThreadFactory

按需创建新线程的对象。使用线程工厂消除了对新线程的调用的硬连线,使应用程序能够使用特殊的线程子类、优先级等。

Thread newThread(Runnable r)

构造一个新线程。实现还可以初始化优先级、名称、守护进程状态、ThreadGroup 等。

示例代码:

import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy;

class SimpleThreadFactory implements ThreadFactory {
   String name;
   AtomicInteger threadNo = new AtomicInteger(0);

   public SimpleThreadFactory (String name){
       this.name = name;
   }
   public Thread newThread(Runnable r) {
     String threadName = name+":"+threadNo.incrementAndGet();
     System.out.println("threadName:"+threadName);
     return new Thread(r,threadName );
   }
   public static void main(String args[]){
        SimpleThreadFactory factory = new SimpleThreadFactory("Factory Thread");
        ThreadPoolExecutor executor= new ThreadPoolExecutor(1,1,60,
                    TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(1),new ThreadPoolExecutor.DiscardPolicy());


        final ExecutorService executorService = Executors.newFixedThreadPool(5,factory);

        for ( int i=0; i < 100; i++){
            executorService.submit(new Runnable(){
                 public void run(){
                    System.out.println("Thread Name in Runnable:"+Thread.currentThread().getName());
                 }
            });
        }
        executorService.shutdown();
    }
 }

输出:

java SimpleThreadFactory

thread no:1
thread no:2
Thread Name in Runnable:Factory Thread:1
Thread Name in Runnable:Factory Thread:2
thread no:3
thread no:4
Thread Name in Runnable:Factory Thread:3
Thread Name in Runnable:Factory Thread:4
thread no:5
Thread Name in Runnable:Factory Thread:5

...等

Extend ThreadFactory

public interface ThreadFactory

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

Thread newThread(Runnable r)

Constructs a new Thread. Implementations may also initialize priority, name, daemon status, ThreadGroup, etc.

Sample code:

import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy;

class SimpleThreadFactory implements ThreadFactory {
   String name;
   AtomicInteger threadNo = new AtomicInteger(0);

   public SimpleThreadFactory (String name){
       this.name = name;
   }
   public Thread newThread(Runnable r) {
     String threadName = name+":"+threadNo.incrementAndGet();
     System.out.println("threadName:"+threadName);
     return new Thread(r,threadName );
   }
   public static void main(String args[]){
        SimpleThreadFactory factory = new SimpleThreadFactory("Factory Thread");
        ThreadPoolExecutor executor= new ThreadPoolExecutor(1,1,60,
                    TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(1),new ThreadPoolExecutor.DiscardPolicy());


        final ExecutorService executorService = Executors.newFixedThreadPool(5,factory);

        for ( int i=0; i < 100; i++){
            executorService.submit(new Runnable(){
                 public void run(){
                    System.out.println("Thread Name in Runnable:"+Thread.currentThread().getName());
                 }
            });
        }
        executorService.shutdown();
    }
 }

output:

java SimpleThreadFactory

thread no:1
thread no:2
Thread Name in Runnable:Factory Thread:1
Thread Name in Runnable:Factory Thread:2
thread no:3
thread no:4
Thread Name in Runnable:Factory Thread:3
Thread Name in Runnable:Factory Thread:4
thread no:5
Thread Name in Runnable:Factory Thread:5

....etc

染墨丶若流云 2024-11-16 07:42:11

使用 执行器的现有功能。 defaultThreadFactory() 但只是设置名称:

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

public class NamingThreadFactory implements ThreadFactory {
    private final String prefix;
    private final AtomicInteger threadNumber = new AtomicInteger(0);

    public NamingThreadFactory(String prefix){
        this.prefix = prefix;
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = Executors.defaultThreadFactory().newThread(r);
        t.setName(prefix + threadNumber.addAndGet(1));
        return t;
    }
}

Using the existing functionality of Executors.defaultThreadFactory() but just setting the name:

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

public class NamingThreadFactory implements ThreadFactory {
    private final String prefix;
    private final AtomicInteger threadNumber = new AtomicInteger(0);

    public NamingThreadFactory(String prefix){
        this.prefix = prefix;
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = Executors.defaultThreadFactory().newThread(r);
        t.setName(prefix + threadNumber.addAndGet(1));
        return t;
    }
}
逆光下的微笑 2024-11-16 07:42:11

根据上面的一些评论,不同之处在于我只使用了 lambda

Executors.newFixedThreadPool(10, r -> new Thread(r, "my-threads-%d"))

Based on few of the comments above, difference is I just used lambda

Executors.newFixedThreadPool(10, r -> new Thread(r, "my-threads-%d"))
复古式 2024-11-16 07:42:11

我经常这样做(需要 guava 库):

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("SO-POOL-%d").build();
ExecutorService executorService = Executors.newFixedThreadPool(5,namedThreadFactory);

I use to do same like below (requires guava library) :

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("SO-POOL-%d").build();
ExecutorService executorService = Executors.newFixedThreadPool(5,namedThreadFactory);
我是男神闪亮亮 2024-11-16 07:42:11

我用来装饰现有工厂的本土核心 Java 解决方案:

public class ThreadFactoryNameDecorator implements ThreadFactory {
    private final ThreadFactory defaultThreadFactory;
    private final String suffix;

    public ThreadFactoryNameDecorator(String suffix) {
        this(Executors.defaultThreadFactory(), suffix);
    }

    public ThreadFactoryNameDecorator(ThreadFactory threadFactory, String suffix) {
        this.defaultThreadFactory = threadFactory;
        this.suffix = suffix;
    }

    @Override
    public Thread newThread(Runnable task) {
        Thread thread = defaultThreadFactory.newThread(task);
        thread.setName(thread.getName() + "-" + suffix);
        return thread;
    }
}

实际应用:

Executors.newSingleThreadExecutor(new ThreadFactoryNameDecorator("foo"));

The home-grown core Java solution that I use to decorate existing factories:

public class ThreadFactoryNameDecorator implements ThreadFactory {
    private final ThreadFactory defaultThreadFactory;
    private final String suffix;

    public ThreadFactoryNameDecorator(String suffix) {
        this(Executors.defaultThreadFactory(), suffix);
    }

    public ThreadFactoryNameDecorator(ThreadFactory threadFactory, String suffix) {
        this.defaultThreadFactory = threadFactory;
        this.suffix = suffix;
    }

    @Override
    public Thread newThread(Runnable task) {
        Thread thread = defaultThreadFactory.newThread(task);
        thread.setName(thread.getName() + "-" + suffix);
        return thread;
    }
}

In action:

Executors.newSingleThreadExecutor(new ThreadFactoryNameDecorator("foo"));
白日梦 2024-11-16 07:42:11
Executors.newSingleThreadExecutor(r -> new Thread(r, "someName")).submit(getJob());

Runnable getJob() {
        return () -> {
            // your job
        };
}
Executors.newSingleThreadExecutor(r -> new Thread(r, "someName")).submit(getJob());

Runnable getJob() {
        return () -> {
            // your job
        };
}
悟红尘 2024-11-16 07:42:11

您可以编写自己的 ThreadFactory 实现,例如使用一些现有的实现(如 defaultThreadFactory)并在最后更改名称。

实现 ThreadFactory 的示例:

class ThreadFactoryWithCustomName implements ThreadFactory {
    private final ThreadFactory threadFactory;
    private final String name;

    public ThreadFactoryWithCustomName(final ThreadFactory threadFactory, final String name) {
        this.threadFactory = threadFactory;
        this.name = name;
    }

    @Override
    public Thread newThread(final Runnable r) {
        final Thread thread = threadFactory.newThread(r);
        thread.setName(name);
        return thread;
    }
}

及用法:

Executors.newSingleThreadExecutor(new ThreadFactoryWithCustomName(
        Executors.defaultThreadFactory(),
        "customName")
    );

You can write your own implementation of ThreadFactory, using for example some existing implementation (like defaultThreadFactory) and change the name at the end.

Example of implementing ThreadFactory:

class ThreadFactoryWithCustomName implements ThreadFactory {
    private final ThreadFactory threadFactory;
    private final String name;

    public ThreadFactoryWithCustomName(final ThreadFactory threadFactory, final String name) {
        this.threadFactory = threadFactory;
        this.name = name;
    }

    @Override
    public Thread newThread(final Runnable r) {
        final Thread thread = threadFactory.newThread(r);
        thread.setName(name);
        return thread;
    }
}

And usage:

Executors.newSingleThreadExecutor(new ThreadFactoryWithCustomName(
        Executors.defaultThreadFactory(),
        "customName")
    );
梦归所梦 2024-11-16 07:42:11

这是我的定制工厂,为线程转储分析器提供定制名称。通常我只是给出 tf=null 来重用 JVM 默认线程工厂。 该网站有更高级的线程工厂。

public class SimpleThreadFactory implements ThreadFactory {
    private ThreadFactory tf;
    private String nameSuffix;

    public SimpleThreadFactory (ThreadFactory tf, String nameSuffix) {
        this.tf = tf!=null ? tf : Executors.defaultThreadFactory();
        this.nameSuffix = nameSuffix; 
    }

    @Override public Thread newThread(Runnable task) {
        // default "pool-1-thread-1" to "pool-1-thread-1-myapp-MagicTask"
        Thread thread=tf.newThread(task);
        thread.setName(thread.getName()+"-"+nameSuffix);
        return thread;
    }
}

- - - - - 

ExecutorService es = Executors.newFixedThreadPool(4, new SimpleThreadFactory(null, "myapp-MagicTask") );

为了您的方便,这是一个用于调试目的的线程转储循环。

    ThreadMXBean mxBean=ManagementFactory.getThreadMXBean();
    long[] tids = mxBean.getAllThreadIds();
    System.out.println("------------");
    System.out.println("ThreadCount="+tids.length);
    for(long tid : tids) {
        ThreadInfo mxInfo=mxBean.getThreadInfo(tid);
        if (mxInfo==null) {
            System.out.printf("%d %s\n", tid, "Thread not found");
        } else {
            System.out.printf("%d %s, state=%s, suspended=%d, lockowner=%d %s\n"
                    , mxInfo.getThreadId(), mxInfo.getThreadName()
                    , mxInfo.getThreadState().toString()
                    , mxInfo.isSuspended()?1:0
                    , mxInfo.getLockOwnerId(), mxInfo.getLockOwnerName()
            );
        }
    }

This is my customized factory providing a customized names for thread dump analyzers. Usually I just give tf=null to reuse JVM default thread factory. This website has more advanced thread factory.

public class SimpleThreadFactory implements ThreadFactory {
    private ThreadFactory tf;
    private String nameSuffix;

    public SimpleThreadFactory (ThreadFactory tf, String nameSuffix) {
        this.tf = tf!=null ? tf : Executors.defaultThreadFactory();
        this.nameSuffix = nameSuffix; 
    }

    @Override public Thread newThread(Runnable task) {
        // default "pool-1-thread-1" to "pool-1-thread-1-myapp-MagicTask"
        Thread thread=tf.newThread(task);
        thread.setName(thread.getName()+"-"+nameSuffix);
        return thread;
    }
}

- - - - - 

ExecutorService es = Executors.newFixedThreadPool(4, new SimpleThreadFactory(null, "myapp-MagicTask") );

For your convenience this is a thread dump loop for debug purpose.

    ThreadMXBean mxBean=ManagementFactory.getThreadMXBean();
    long[] tids = mxBean.getAllThreadIds();
    System.out.println("------------");
    System.out.println("ThreadCount="+tids.length);
    for(long tid : tids) {
        ThreadInfo mxInfo=mxBean.getThreadInfo(tid);
        if (mxInfo==null) {
            System.out.printf("%d %s\n", tid, "Thread not found");
        } else {
            System.out.printf("%d %s, state=%s, suspended=%d, lockowner=%d %s\n"
                    , mxInfo.getThreadId(), mxInfo.getThreadName()
                    , mxInfo.getThreadState().toString()
                    , mxInfo.isSuspended()?1:0
                    , mxInfo.getLockOwnerId(), mxInfo.getLockOwnerName()
            );
        }
    }
半衬遮猫 2024-11-16 07:42:11

我想我会抛出一些简化的示例,这样选项就全部存在:

唯一编号(也可以将其放入方法中):

AtomicInteger threadNum = new AtomicInteger(0);
ExecutorService e = Executors.newSingleThreadExecutor(r -> new Thread(r, "my-name-" + threadNum.incrementAndGet()));

唯一编号和“可能”唯一名称(如果您正在生成新的 Runnable 对象)。如果在多次调用的方法中启动线程,则很有用,例如:

AtomicInteger threadNum = new AtomicInteger(0);
ExecutorService e = Executors.newSingleThreadExecutor(r -> new Thread(r, "my-name-" + threadNum.incrementAndGet() + "-" + r.hashCode()));

如果您每次需要一个具有静态变量的类时确实想要一个唯一的名称(并且还可以在也有,请参阅其他答案)。

以及 JDK 中的等效项 < 8(您不需要为其创建一个新类,或者可以从方法中返回 ThreadFactory):

Executors.newSingleThreadExecutor(new ThreadFactory() {
      AtomicInteger threadCount = new AtomicInteger(0);

      @Override
      public Thread newThread(Runnable r) {
        return new Thread(r, "your-name-" + threadCount.getAndIncrement() + "-" + r.hashCode()); // could also use Integer.toHexString(r.hashCode()) for shorter
      }
    }));

并且可以将其作为变量作为“you-name-”方面的方法。或者像其他答案一样使用带有构造函数的单独类。

Thought I'd throw in some simplified examples, just so the options are all out there:

Unique number (could also put this into a method):

AtomicInteger threadNum = new AtomicInteger(0);
ExecutorService e = Executors.newSingleThreadExecutor(r -> new Thread(r, "my-name-" + threadNum.incrementAndGet()));

Unique number and "probably" unique name (if you're generating new Runnable objects). Useful if starting off the threads is within a method that gets called more than once, for instance:

AtomicInteger threadNum = new AtomicInteger(0);
ExecutorService e = Executors.newSingleThreadExecutor(r -> new Thread(r, "my-name-" + threadNum.incrementAndGet() + "-" + r.hashCode()));

If you really wanted a unique name each time you'd need a class with a static var (and could also add a static pool number prefix in there as well, see other answers).

and an equivalent in JDK < 8 (you don't need a new class for it, or could return a ThreadFactory out of a method):

Executors.newSingleThreadExecutor(new ThreadFactory() {
      AtomicInteger threadCount = new AtomicInteger(0);

      @Override
      public Thread newThread(Runnable r) {
        return new Thread(r, "your-name-" + threadCount.getAndIncrement() + "-" + r.hashCode()); // could also use Integer.toHexString(r.hashCode()) for shorter
      }
    }));

And could make that into a method for the "you-name-" aspect as a variable. Or use a separate class with a constructor like the other answers all seem to.

迷离° 2024-11-16 07:42:11

从 Java 21 开始

Executors.newSingleThreadExecutor(Thread.ofPlatform().name("FooPool-FooThread-",1).factory());

或对于 4 个线程的池:

Executors.newFixedThreadPool(4,Thread.ofPlatform().name("FooPool-FooThread-",1).factory());

Since Java 21

Executors.newSingleThreadExecutor(Thread.ofPlatform().name("FooPool-FooThread-",1).factory());

or for a pool of 4 threads:

Executors.newFixedThreadPool(4,Thread.ofPlatform().name("FooPool-FooThread-",1).factory());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文