我可以访问线程池线程提交的任务(并且正在运行)的线程吗?

时间:2019-03-15 18:21:17

标签: java multithreading threadpool executorservice thread-local

我想覆盖protected void beforeExecute(Thread t, Runnable r) { }ThreadPoolExecutorMyThreadPoolExecutor的{​​{1}},在那里我想知道哪个线程已提交了该(t)线程要执行的任务跑?我想将提交线程的threadLocals的任务复制到将要运行此任务的线程({t)中(在threadPool中)。

2 个答案:

答案 0 :(得分:1)

我设法做到了

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);
    }

}

答案 1 :(得分:0)

我相信您可以在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