使用ThreadPoolExecutor,如何获取线程池中运行的线程的名称? [英] With ThreadPoolExecutor, how to get the name of the thread running in the thread pool?

查看:1051
本文介绍了使用ThreadPoolExecutor,如何获取线程池中运行的线程的名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Java中使用 ThreadPoolExecutor 来管理大量正在运行的线程。我创建了自己的简单 ThreadFactory 所以我可以给线程更好的名字。

I'm using a ThreadPoolExecutor in Java to manage a lot of running threads. I've created my own simple ThreadFactory so I can give the threads better names.

问题在于首次创建线程池时,名称在线程中设置,并且不与线程池实际运行的任务相关联。我理解这一点......我的Runnables和Callables - 尽管它们有名字 - 实际上是从 ThreadPoolExecutor 运行线程的一个抽象层次。

The issue is that the name gets set in the Thread when the thread pool is first created and is not tied to the task that the thread pool is actually running. I understand this... my Runnables and Callables--though they have names--are actually one level of abstraction down from the ThreadPoolExecutor's running threads.

StackOverflow上还有一些关于为 ThreadPoolExecutor 线程池创建名称的问题。 (请参阅如何为可调用线程命名?如何命名线程池的线程Java 。)

There have been some other questions on StackOverflow about creating names for ThreadPoolExecutor thread pools. (See How to give name to a callable Thread? and How to name the threads of a thread pool in Java.)

我想知道的是:有没有人有一个很好的解决方案来保持线程池线程的名称与Runnable保持同步它实际上在运行?

What I want to know is: does anyone have a good solution for keeping the name of the thread pool thread in sync with the Runnable that it is actually running?

ie如果我调用 Thread.getCurrentThread()。getName()我希望它 not 返回顶级线程池的名称,而是线程当前正在运行的Callable / Runnable的名称。

i.e. If I call Thread.getCurrentThread().getName() I'd like it not to return the name of the top-level thread pool, but rather the name of the Callable/Runnable that the thread is currently running.

由于这主要是出于调试和日志记录的目的,我试图避免一个解决方案涉及我将新代码放入可能提交给ThreadPoolExecutor的每个Runnable中 - 我只是将一些代码放入ThreadFactory或包装ThreadPoolExecutor本身,以便在一个地方完成更改。如果不存在这样的解决方案,我可能不会打扰,因为它不是关键任务。

Since this is mainly for debugging and logging purposes, I'm trying to avoid a solution that involves me putting new code into every Runnable that might be submitted to the ThreadPoolExecutor--I'd rather just put some code into the ThreadFactory or wrap the ThreadPoolExecutor itself so that the change is done in one place. If such a solution doesn't exist I probably won't bother since it's not mission critical.

开始编辑 为了澄清,我知道我可以将 Thread.currentThread()。setName(我的runnable name); 作为每个Runnable的run方法的第一行,但是我我试图避免这样做。我在这里是一个完美主义者,我意识到这一点,所以如果人们想对这个问题发表评论并告诉我,我不会被冒犯。 结束编辑

begin edit To clarify, I know I can put a Thread.currentThread().setName( "my runnable name" ); as the first line of every Runnable's run method, but I'm trying to avoid doing that. I'm being a perfectionist here, and I realize it, so I won't be offended if people want to comment on this question and tell me so. end edit

我想,我的另一个问题是人们是否认为这样做是个坏主意事情。我是否应该像这样更新线程池名称?

My other question, I suppose, is whether people think it's a bad idea to do such a thing. Should I be wary of updating the thread pool name like this?

感谢您的任何建议!

推荐答案

创建一个覆盖beforeExecute方法的ThreadPoolExecutor。

Create a ThreadPoolExecutor that overrides the beforeExecute method.

private final ThreadPoolExecutor executor = new ThreadPoolExecutor (new ThreadPoolExecutor(10, 10,  0L, TimeUnit.MILLISECONDS,  new LinkedBlockingQueue<Runnable>()){   
    protected void beforeExecute(Thread t, Runnable r) { 
         t.setName(deriveRunnableName(r));
    }

    protected void afterExecute(Runnable r, Throwable t) { 
         Thread.currentThread().setName("");
    } 

    protected <V> RunnableFuture<V> newTaskFor(final Runnable runnable, V v) {
         return new FutureTask<V>(runnable, v) {
             public String toString() {
                return runnable.toString();
             }
         };
     };
}

不确定 derveRunnableName()究竟是如何工作的,也许 toString()

Not sure how exactly derveRunnableName() would work, maybe toString()?

编辑:Thread.currentThread()实际上是在beforeExecute中设置的线程它调用afterExecute。您可以引用Thread.currentThread(),然后在afterExecute中设置名称。这在javadocs中注明

The Thread.currentThread() is in fact the thread being set in beforeExecute which calls the afterExecute. You can reference Thread.currentThread() and then set the name in the afterExecute. This is noted in the javadocs

/**
 * Method invoked upon completion of execution of the given Runnable.
 * This method is invoked by the thread that executed the task. If
 * non-null, the Throwable is the uncaught <tt>RuntimeException</tt>
 * or <tt>Error</tt> that caused execution to terminate abruptly.
 *
 * <p><b>Note:</b> When actions are enclosed in tasks (such as
 * {@link FutureTask}) either explicitly or via methods such as
 * <tt>submit</tt>, these task objects catch and maintain
 * computational exceptions, and so they do not cause abrupt
 * termination, and the internal exceptions are <em>not</em>
 * passed to this method.
 *
 * <p>This implementation does nothing, but may be customized in
 * subclasses. Note: To properly nest multiple overridings, subclasses
 * should generally invoke <tt>super.afterExecute</tt> at the
 * beginning of this method.
 *
 * @param r the runnable that has completed.
 * @param t the exception that caused termination, or null if
 * execution completed normally.
 */
protected void afterExecute(Runnable r, Throwable t) { }

编辑 TPE会将Runnable包装在FutureTask中,因此要支持 toString 方法,您可以覆盖 newTaskFor 并创建自己的包装FutureTask。

Edit The TPE will wrap the Runnable within a FutureTask, so to support the toString method you could override newTaskFor and create your own wrapped FutureTask.

这篇关于使用ThreadPoolExecutor,如何获取线程池中运行的线程的名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆