当前位置: 首页 > 面试题库 >

使用ThreadPoolExecutor,如何获取在线程池中运行的线程的名称?

葛承德
2023-03-14
问题内容

ThreadPoolExecutor在Java中使用A
来管理许多正在运行的线程。我创建了自己的简单名称,ThreadFactory以便为线程命名。

问题在于,在首次创建线程池时会在线程中设置名称,并且该名称与线程池实际正在运行的任务无关。我了解这一点…尽管我的Runnable和Callables具有名称,但它们实际上是从ThreadPoolExecutor的运行线程开始的抽象层。

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

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

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

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

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

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

感谢您的任何建议!


问题答案:

创建一个重写beforeExecute方法的ThreadPoolExecutor。

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()

编辑:Thread.currentThread()实际上是在调用afterExecute的beforeExecute中设置的线程。您可以引用Thread.currentThread(),然后在afterExecute中设置名称。这在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。



 类似资料:
  • 本文向大家介绍ThreadPoolExecutor线程池的使用方法,包括了ThreadPoolExecutor线程池的使用方法的使用技巧和注意事项,需要的朋友参考一下 ThreadPoolExecutor ThreadPoolExecutor线程池,java提供开发框架,管理线程的创建、销毁、优化、监控等。 有4种不同的任务队列: 1.ArrayBlockingQueue:基于数组结构的任务队列。

  • 问题内容: 我有一个使用该框架的Java应用程序,并且我的代码看起来像这样 我的理解是,JVM会在内部创建5个线程的池。现在,当我在探查器中检查执行情况时,会得到类似的信息。 , 我需要一种方法来区分由我创建的和由服务器创建的 。 我在想,如果我可以命名线程池,它应该可以解决问题,但是看不到任何允许我执行此操作的API。 提前致谢。 问题答案: 您可以将自己的ThreadFactory传递给Sch

  • 本文向大家介绍Java ThreadPoolExecutor 线程池的使用介绍,包括了Java ThreadPoolExecutor 线程池的使用介绍的使用技巧和注意事项,需要的朋友参考一下 Executors Executors 是一个Java中的工具类. 提供工厂方法来创建不同类型的线程池. 从上图中也可以看出, Executors的创建线程池的方法, 创建出来的线程池都实现了 Executo

  • 问题内容: 我有一个固定的线程池,我可以将任务提交给该线程池(限制为 5个 线程)。如何找出这 5个 线程中的哪一个执行我的任务(例如“第3 个 线程中的第3 个 线程正在执行此任务”)? 问题答案: 使用:

  • 本文向大家介绍Android之线程池ThreadPoolExecutor的简介,包括了Android之线程池ThreadPoolExecutor的简介的使用技巧和注意事项,需要的朋友参考一下 Android中的线程池ThreadPoolExecutor解决了单线程下载数据的效率慢和线程阻塞的的问题,它的应用也是优化实现的方式。所以它的重要性不言而喻,但是它的复杂性也大,理解上可能会有问题,不过作为

  • 问题内容: 在我们的软件中,我们广泛使用MDC来跟踪Web请求的内容,例如会话ID和用户名。在原始线程中运行时,这可以正常工作。但是,有很多事情需要在后台处理。为此,我们使用java.concurrent.ThreadPoolExecutor和java.util.Timer类以及一些自卷式异步执行服务。所有这些服务都管理自己的线程池。 这是Logback手册关于在这样的环境中使用MDC的内容: 映