如何为可调用线程命名?

发布于 2024-09-09 10:00:27 字数 480 浏览 4 评论 0原文

我正在使用 ExecutorService 线程池执行可调用对象。我想给这个线程起一个名字。

更具体地说,在旧版本中我这样做了 -

Thread thread = new Thread(runnable Task);
thread.setName("My Thread Name");

我在 log4j 日志记录中使用线程名称,这在故障排除时有很大帮助。现在我正在将代码从 Java 1.4 迁移到 Java 1.6。我已经写了这个(如下)-但我不知道如何给这个线程命名。

private final ExecutorService executorPool = Executors.newCachedThreadPool();
Future<String> result = executorPool.submit(callable Task);

请给我一些想法来给这个线程命名?

I am executing a Callable Object using ExecutorService thread pool. I want to give a name to this thread.

To be more specific, in older version I did this -

Thread thread = new Thread(runnable Task);
thread.setName("My Thread Name");

I use thread name in log4j logging, this helps a lot while troubleshooting. Now I am migrating my code from Java 1.4 to Java 1.6. I have written this(Given below)- but I dont know how to give name to this thread.

private final ExecutorService executorPool = Executors.newCachedThreadPool();
Future<String> result = executorPool.submit(callable Task);

Please give me some idea to give name to this thread?

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

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

发布评论

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

评论(8

懷念過去 2024-09-16 10:00:27

我目前正在这样做:

    someExecutor.execute(new Runnable() {
        @Override public void run() {
            final String orgName = Thread.currentThread().getName();
            Thread.currentThread().setName(orgName + " - My custom name here");
            try {
                myAction();
            } finally {
                Thread.currentThread().setName(orgName);
            }
        }
    });

I'm currently doing it somewhat like this:

    someExecutor.execute(new Runnable() {
        @Override public void run() {
            final String orgName = Thread.currentThread().getName();
            Thread.currentThread().setName(orgName + " - My custom name here");
            try {
                myAction();
            } finally {
                Thread.currentThread().setName(orgName);
            }
        }
    });
表情可笑 2024-09-16 10:00:27

您可以使用重载方法:

java.util.concurrent.Executors.newCachedThreadPool(ThreadFactory)

它允许您传递一个

java.util.concurrent.ThreadFactory

允许您通过 java.util.concurrent.ThreadFactory.newThread(Runnable) 设置线程名称的方法:

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

请查看 java.util.concurrent.Executors.DefaultThreadFactory 以了解默认实现。

附录

由于我发现该线程仍然被访问,Guava(如果有的话)提供了ThreadFactoryBuilder 利用了内部匿名类的需求,甚至允许为您的自定义参数化名称线程。

You may use the overloaded method:

java.util.concurrent.Executors.newCachedThreadPool(ThreadFactory)

which allows you to pass a

java.util.concurrent.ThreadFactory

that should allow you to set the thread's names via java.util.concurrent.ThreadFactory.newThread(Runnable):

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

Have a look at java.util.concurrent.Executors.DefaultThreadFactory for a default implementation.

Addendum

Since I see that this thread is still visited, Guava (if you have it available) provides a ThreadFactoryBuilder that leverages the need of having an inner anonymous class and even allows for customizing parametrized names for your threads.

孤独岁月 2024-09-16 10:00:27
/**
 * The default thread factory
 */
static class DefaultThreadFactory implements ThreadFactory {
    static final AtomicInteger poolNumber = new AtomicInteger(1);
    final ThreadGroup group;
    final AtomicInteger threadNumber = new AtomicInteger(1);
    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;
    }
}

这是 Java 1.5.0 中的原始实现。因此,实际上名称为 pool-x-thread,其中 x 代表当前线程组中线程的顺序。

/**
 * The default thread factory
 */
static class DefaultThreadFactory implements ThreadFactory {
    static final AtomicInteger poolNumber = new AtomicInteger(1);
    final ThreadGroup group;
    final AtomicInteger threadNumber = new AtomicInteger(1);
    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;
    }
}

This is the original implementation in Java 1.5.0. So, you actually have the names as pool-x-thread where x stands for the order of the thread in the current thread group.

疯了 2024-09-16 10:00:27

当线程由线程池管理时,重命名线程时应该小心,因为它们实际上会一遍又一遍地重复用于不同的任务,并且一旦重命名,您可能会发现日志中的线程名称没有任何意义...为了避免这种不需​​要的行为,您应该确保一旦您的 Runnable/Callable 完成,线程名称就会恢复。

实现此目的的一种方法是使用装饰器包装线程池执行的每个 Runnable/Callable,该装饰器处理所有需要的清理工作。

You should be careful when renaming threads when your threads are managed by a thread-pool because they are actually being reused over and over again for different tasks and once renamed, you might find that the thread names in your logs don't make any sense... In order to avoid that unwanted behavior you should make sure that once your Runnable/Callable finished the thread name is restored.

One way to implement this is by wrapping every Runnable/Callable that is executed by the thread-pool with a decorator which handles all of the needed clean-ups.

巨坚强 2024-09-16 10:00:27

如果您使用 Spring,则可以使用 org.springframework.scheduling.concurrent.CustomizedThreadFactory 为此:

ExecutorService executorService = Executors.newCachedThreadPool(
                             new CustomizableThreadFactory("MyThreadNamePrefix"));

If you are using Spring, you may use org.springframework.scheduling.concurrent.CustomizableThreadFactory for that:

ExecutorService executorService = Executors.newCachedThreadPool(
                             new CustomizableThreadFactory("MyThreadNamePrefix"));
仙女山的月亮 2024-09-16 10:00:27

我只需要做你所要求的——为我的线程组提供名称——所以感谢 Andeas 的回答,我创建了自己的 ThreadFactory 作为将要通过复制 Executors$DefaultThreadFactory 来使用它的类的内部类,通过将参数“groupname”添加到构造函数来更改 3 行。

    /**
 * A thread factory that names each thread with the provided group name.
 * <p>
 * Except lines with "elarson modified", copied from code 
 * Executors$DefaultThreadFactory -- Doug Lea, Copyright Oracle, et al.
 */
static class GroupNameThreadFactory implements ThreadFactory {
    private String groupname; /* elarson modified */
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    GroupNameThreadFactory(String groupname) {
        this.groupname = groupname; /* elarson modified */
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                              Thread.currentThread().getThreadGroup();
        namePrefix = "pool-" +
                       this.groupname + /* elarson modified */
                       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;
    }
}

从它创建一个线程池的过程如下。

        ThreadFactory threadfactory = new GroupNameThreadFactory("Monitor");    
    executor = Executors.newFixedThreadPool(NUM_THREADS, threadfactory);

感谢 user381878 提出问题,感谢 Andreas 的回答。

I just had to do what you are asking for -- providing names to my thread groups -- so thanks to Andeas's answer, I created my own ThreadFactory as an inner-class to the class that is going to use it by copying Executors$DefaultThreadFactory, changing 3 lines by adding the parameter "groupname" to the constructor.

    /**
 * A thread factory that names each thread with the provided group name.
 * <p>
 * Except lines with "elarson modified", copied from code 
 * Executors$DefaultThreadFactory -- Doug Lea, Copyright Oracle, et al.
 */
static class GroupNameThreadFactory implements ThreadFactory {
    private String groupname; /* elarson modified */
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    GroupNameThreadFactory(String groupname) {
        this.groupname = groupname; /* elarson modified */
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                              Thread.currentThread().getThreadGroup();
        namePrefix = "pool-" +
                       this.groupname + /* elarson modified */
                       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;
    }
}

Creating a ThreadPool from it is done as follows.

        ThreadFactory threadfactory = new GroupNameThreadFactory("Monitor");    
    executor = Executors.newFixedThreadPool(NUM_THREADS, threadfactory);

Thanks user381878 for asking the question, and Andreas for the answer.

不知在何时 2024-09-16 10:00:27

只需创建一个匿名ThreadFactory来获取Executor Service即可。
ThreadFactory 可以提供线程的名称,如下所示:“Thread A”或“Thread B”(请参见示例)。

然后使用不同的执行器服务调用可调用任务:

示例类:

public class ThreadTester {

public static void main(String[] args) {
    ThreadTester threadTester = new ThreadTester();
    threadTester.test();
}

private void test() {

    ExecutorService executorservice = Executors.newCachedThreadPool(new ThreadFactory() {

        @Override
        public Thread newThread(Runnable arg0) {
            return new Thread(arg0,"Thread A");
        }
    });

    CallableTask taskA = new CallableTask();
    executorservice.submit(taskA);

    executorservice = Executors.newCachedThreadPool(new ThreadFactory() {

        @Override
        public Thread newThread(Runnable arg0) {
            return new Thread(arg0,"Thread B");
        }
    });
    CallableTask taskB = new CallableTask();
    executorservice.submit(taskB);
}

}

Callable Task :

public class CallableTask Implements Callable {

@Override
public Integer call() throws Exception {
    int sum = 0;

    for(int count=1;count<=30;count++){
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " Count :"+count);
        sum = sum + count;
    }
    System.out.println(Thread.currentThread().getName() + " Sum :"+sum);
    return sum;
}

}

Just create an anonymous ThreadFactory for getting the Executor Service.
The ThreadFactory can supply the name for the thread as follows: "Thread A" or "Thread B" (see the example).

Then call the callable task using the different executor services:

Example Class:

public class ThreadTester {

public static void main(String[] args) {
    ThreadTester threadTester = new ThreadTester();
    threadTester.test();
}

private void test() {

    ExecutorService executorservice = Executors.newCachedThreadPool(new ThreadFactory() {

        @Override
        public Thread newThread(Runnable arg0) {
            return new Thread(arg0,"Thread A");
        }
    });

    CallableTask taskA = new CallableTask();
    executorservice.submit(taskA);

    executorservice = Executors.newCachedThreadPool(new ThreadFactory() {

        @Override
        public Thread newThread(Runnable arg0) {
            return new Thread(arg0,"Thread B");
        }
    });
    CallableTask taskB = new CallableTask();
    executorservice.submit(taskB);
}

}

Callable Task :

public class CallableTask implements Callable {

@Override
public Integer call() throws Exception {
    int sum = 0;

    for(int count=1;count<=30;count++){
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " Count :"+count);
        sum = sum + count;
    }
    System.out.println(Thread.currentThread().getName() + " Sum :"+sum);
    return sum;
}

}

梦幻的心爱 2024-09-16 10:00:27

我使用过的一种方法,在我的例子中,我有多个由单个类控制的并行获取数据的 future。我提交了一些工作并拿回了期货。我将未来存储在地图中,并将值作为作业名称。
然后,当我对所有 future 进行超时处理时,我从地图上得到了作业的名称。这可能不是最灵活的方式,但在我的情况下有效。

One approach that I've used, and in my case I had a number of futures fetching data in parallel controlled by a single class. I submit a number of jobs and get the futures back. I store the future in a map with the value as the job name.
Then later on, when I'm doing a get with a timeout on all futures I have the name of the job from the map. It's not maybe the most flexible way but worked in my situation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文