call线程起名字_使用ThreadPoolExecutor,如何获取线程池中运行的线程的名称?

本文转载自优快云博主「伟信优39575758」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.youkuaiyun.com/weixin_39575758/article/details/111808004

本文系转载,如有侵权请联系删除。原文为英文,为便于自己理解,翻译了一下。

我在Java中使用ThreadPoolExecutor来管理许多正在运行的线程。我已经创建了自己的简单线程工厂,这样我可以给线程起更好的名字。

问题是,第一次创建线程池时,该名称在线程中设置,并且与线程池实际运行的任务无关。我理解。。。我的Runnable和Callable(虽然它们有名称)实际上是ThreadPoolExecutor运行线程的一个抽象级别。

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

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

i、 如果我调用线程.getCurrentThread().getName()我不希望返回顶级线程池的名称,而是返回线程当前正在运行的可调用/可运行线程的名称。

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

澄清,我知道我可以放一个线程.currentThread().setName(“我的可运行名称”);作为每个Runnable的run方法的第一行,但我尽量避免这样做。我在这里是一个完美主义者,我意识到这一点,所以如果人们想评论这个问题并告诉我,我不会生气。

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

谢谢你的建议!

解决方案

创建重写beforeExecute方法的ThreadPoolExecutor。

private final ThreadPoolExecutor executor = new ThreadPoolExecutor (new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()){

    protected void beforeExecute(Thread t, Runnable r) {

        t.setName(deriveRunnableName(r));

    }

    protected void afterExecute(Runnable r, Throwable t) {

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

    }

    protected RunnableFuture newTaskFor(final Runnable runnable, V v) {

        return new FutureTask(runnable, v) {

            public String toString() {

                return runnable.toString();

            }

        };

    };
}

不确定驱动RunnableName()的具体工作方式,可能是toString()?

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

/**

*方法在给定Runnable的执行完成时调用。

*此方法由执行任务的线程调用。如果

*非null,可丢弃的是未捕获的RuntimeException

*或导致执行突然终止的错误。

*

*

注意:当动作包含在任务中时(例如

*{@link FutureTask})显式或通过以下方法

*提交,这些任务对象捕获并维护

*计算异常,因此它们不会导致

*终止,内部例外情况不包括

*传递给此方法。

*

*

此实现不起任何作用,但可以在中进行自定义

*子类。注意:为了正确嵌套多个重写,子类

*通常应调用super。在执行后

*此方法的开始。

*

*@param r已完成的可运行程序。

*@param t导致终止的异常,如果

*执行正常完成。

*/

受保护的void afterExecute(Runnable r,Throwable t){}

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

————————————————

版权声明:本文为优快云博主「伟信优39575758」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.youkuaiyun.com/weixin_39575758/article/details/111808004

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值