【问题标题】:Can I get an access to the thread which submitted task (and is running) for the thread of threadpool?我可以访问为线程池线程提交任务(并且正在运行)的线程吗?
【发布时间】:2019-08-06 21:22:08
【问题描述】:

我想在MyThreadPoolExecutor 中覆盖ThreadPoolExecutor 中的protected void beforeExecute(Thread t, Runnable r) { },我想知道哪个线程提交了这个(t)线程要运行的任务?我想将任务提交线程的 threadLocals 复制到要运行此任务的线程(t)(在 threadPool 中)。

【问题讨论】:

  • 在任何设计中,通常线程执行线程并不关心提交它的线程是什么,但如果你真的想要它,你可以在提交时将线程id保存在任务中。

标签: java multithreading threadpool executorservice thread-local


【解决方案1】:

我相信你可以在你的 runnable 中做这样的事情来获取它正在执行的线程 id。

private class MyTask implements Runnable {
public void run() {
    long threadId = Thread.currentThread().getId();
    logger.debug("Thread # " + threadId + " is doing this task");
}

如果您想尝试让线程池在 ThreadLocal 中执行更棘手的线程,最好的方法是在可运行类中访问 ThreadLocal。

我也在一个网站上阅读了这篇文章,并认为您可能需要重新考虑使用本地线程的自定义线程池的方法。

如果我们想使用 ExecutorService 并向其提交 Runnable,使用 ThreadLocal 将产生不确定的结果——因为我们不能保证给定 userId 的每个 Runnable 操作每次都会由同一个线程处理它被执行了。

因此,我们的 ThreadLocal 将在不同的 userId 之间共享。这就是为什么我们不应该将 TheadLocal 与 ExecutorService 一起使用。只有当我们完全控制哪个线程将选择执行哪个可运行操作时才应该使用它。

https://www.baeldung.com/java-threadlocal

【讨论】:

  • 我正在从我的代码中的多个位置向这个线程池提交任务。不想将这些任务更改为 MyTask。编辑:以及@Robert 所说的。
  • 这为您提供了运行 Runnable 的线程,Sagar 要求提供提交作业的线程...
【解决方案2】:

我成功了

public class MyThreadPoolExecutor extends ThreadPoolExecutor {

    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
            BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    @Override
    public Future<?> submit(Runnable task) {
    // get the threadLocal from current thread which is task submitting thread  
        boolean threadLocalValueFromParentThread = ThreadLocalsUtils.getThreadLocalValueForThisThread.get();

        Runnable wrappedTask = () -> {
            try {
                // set value of task submitting thread's value in whichever thread gets this runnable.
                ThreadLocalsUtils.setThreadLocalValueForThisThread(threadLocalValueFromParentThread);
                task.run();
            } finally {
                ThreadLocalsUtils.setThreadLocalValueForThisThread(false);
            }
        };
        return super.submit(wrappedTask);
    }

}

【讨论】:

  • 这将导致错误:如果我们想使用 ExecutorService 并向其提交 Runnable,使用 ThreadLocal 将产生不确定的结果——因为我们不能保证给定的每个 Runnable 操作userId 每次执行都会被同一个线程处理。
  • 好吧,如果你在 runnable 完成后不移除 threadPool 和 threadLocal,它可能是一个致命的组合。请参阅上面的 finally 块。我从将要运行的线程中故意将其设置为 false(基本上是删除它)wrappedTask
  • baeldung.com/java-threadlocal该链接更详细地解释了它,使用线程本地最好使用用户ID
  • 为什么不实现一个Runnable任务来运行你想要的逻辑,但是你在创建它的时候把当前线程id保存在构造函数中?
猜你喜欢
  • 1970-01-01
  • 2016-06-24
  • 2010-10-10
  • 2013-04-12
  • 2012-10-29
  • 1970-01-01
  • 1970-01-01
  • 2015-06-26
  • 1970-01-01
相关资源
最近更新 更多