Java 如何为可调用线程命名?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3227040/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to give name to a callable Thread?
提问by user381878
I am executing a Callable Object using ExecutorService thread pool. I want to give a name to this thread.
我正在使用 ExecutorService 线程池执行可调用对象。我想给这个线程起个名字。
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.
我在 log4j 日志记录中使用线程名称,这在故障排除时有很大帮助。现在我正在将我的代码从 Java 1.4 迁移到 Java 1.6。我写了这个(下面给出)-但我不知道如何给这个线程命名。
private final ExecutorService executorPool = Executors.newCachedThreadPool();
Future<String> result = executorPool.submit(callable Task);
Please give me some idea to give name to this thread?
请给我一些想法给这个线程命名?
采纳答案by Andreas
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)
:
这应该允许您通过以下方式设置线程的名称java.util.concurrent.ThreadFactory.newThread(Runnable)
:
Constructs a new
Thread
. Implementations may also initialize priority, name, daemon status,ThreadGroup
, etc.
构造一个新的
Thread
. 实现还可以初始化优先级、名称、守护进程状态ThreadGroup
等。
Have a look at java.util.concurrent.Executors.DefaultThreadFactory
for a default implementation.
查看java.util.concurrent.Executors.DefaultThreadFactory
默认实现。
Addendum
附录
Since I see that this thread is still visited, Guava (if you have it available) provides a ThreadFactoryBuilderthat leverages the need of having an inner anonymous class and even allows for customizing parametrized names for your threads.
因为我看到这个线程仍然被访问,Guava(如果你有的话)提供了一个 ThreadFactoryBuilder,它利用了内部匿名类的需要,甚至允许为你的线程自定义参数化名称。
回答by Shai
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.
当您的线程由线程池管理时,重命名线程时应该小心,因为它们实际上被一遍又一遍地重复用于不同的任务,一旦重命名,您可能会发现日志中的线程名称没有任何意义...为了避免这种不需要的行为,您应该确保一旦您的 Runnable/Callable 完成,线程名称就会恢复。
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.
实现这一点的一种方法是将线程池执行的每个 Runnable/Callable 包装成一个装饰器,该装饰器处理所有需要的清理工作。
回答by MTSan
/**
* 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.
这是 Java 1.5.0 中的原始实现。因此,您实际上有名称为 pool-x-thread,其中 x 代表当前线程组中线程的顺序。
回答by Bart van Heukelom
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);
}
}
});
回答by Eric Larson
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.
我只需要按照您的要求去做——为我的线程组提供名称——所以感谢 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;
}
}
Creating a ThreadPool from it is done as follows.
从它创建一个 ThreadPool 的操作如下。
ThreadFactory threadfactory = new GroupNameThreadFactory("Monitor");
executor = Executors.newFixedThreadPool(NUM_THREADS, threadfactory);
Thanks user381878 for asking the question, and Andreas for the answer.
感谢 user381878 提出问题,感谢 Andreas 的回答。
回答by Konstantin Pavlov
If you are using Spring, you may use org.springframework.scheduling.concurrent.CustomizableThreadFactoryfor that:
如果您使用的是 Spring,您可以使用org.springframework.scheduling.concurrent.CustomizableThreadFactory来实现:
ExecutorService executorService = Executors.newCachedThreadPool(
new CustomizableThreadFactory("MyThreadNamePrefix"));
回答by Nipin P
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).
只需创建一个匿名 ThreadFactory 来获取 Executor 服务。ThreadFactory 可以为线程提供如下名称:“线程 A”或“线程 B”(参见示例)。
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 {
公共类 CallableTask 实现 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;
}
}
}
回答by Arun Ramakrishnan
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.
我使用过的一种方法,在我的例子中,我有许多由单个类控制的并行获取数据的期货。我提交了一些工作并取回了期货。我将未来存储在地图中,并将值作为作业名称。然后,当我对所有期货进行超时获取时,我从地图中获得了作业的名称。这可能不是最灵活的方式,但在我的情况下有效。