如何获取线程池ThreadPoolExecutor正在运行的线程

Posted itbac

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何获取线程池ThreadPoolExecutor正在运行的线程相关的知识,希望对你有一定的参考价值。

如何获取线程池ThreadPoolExecutor正在运行的线程?
这里有两种方法,如下代码:
package com.itbac.thread;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.*;
import java.util.stream.Stream;

/**
 * ThreadPoolExecutor 的  beforeExecute() 和 afterExecute()方法,
 * 不是继承自 AbstractExecutorService , 这是设计上的一个败笔。
 * 例如 netty 就是去实现 AbstractExecutorService的
 *
 * 线程池问题:如何获取线程池ThreadPoolExecutor正在运行的线程?
 */
public class ThreadPoolExecutorThreadQuestion {
    public static void main(String[] args) throws InterruptedException {

        //main 线程启动子线程,子线程的创造来自于 Executors.defaultThreadFactory()

        ExecutorService executorService = Executors.newCachedThreadPool();
        //定义线程容器,通过java的引用类型记录数据。
        Set<Thread> threadsContainer = new HashSet<>();
        //自定义的方法
        setThreadFactory(executorService, threadsContainer);

        for (int i = 0; i < 5; i++) {
            executorService.submit(() -> {
            });
        }
        //线程池等待执行 3 ms
        executorService.awaitTermination(3, TimeUnit.MILLISECONDS);

        threadsContainer.stream().
                //过滤调不存活
                filter(Thread::isAlive).
                forEach(thread ->  System.out.println("方法1:线程池的线程:" + thread)
        );

        //方法二:
        Thread mainThread = Thread.currentThread();
        ThreadGroup mainThreadThreadGroup = mainThread.getThreadGroup();
        //获取线程组中的线程。
        int count = mainThreadThreadGroup.activeCount();
        System.out.println("count:"+count);
        Thread[] threads = new Thread[count];
        //enumerate 枚举,recurse 递归
        mainThreadThreadGroup.enumerate(threads, true);
        Stream.of(threads).filter(Thread::isAlive).forEach(thread -> System.out.println("方法2:线程池的线程:" + thread ));

        //关闭线程池
        executorService.shutdown();

        /**
         *  输出结果:
         方法1:线程池的线程:Thread[pool-1-thread-3,5,main]
         方法1:线程池的线程:Thread[pool-1-thread-1,5,main]
         方法1:线程池的线程:Thread[pool-1-thread-4,5,main]
         方法1:线程池的线程:Thread[pool-1-thread-5,5,main]
         方法1:线程池的线程:Thread[pool-1-thread-2,5,main]
         count:7
         方法2:线程池的线程:Thread[main,5,main]     主线程
         方法2:线程池的线程:Thread[Monitor Ctrl-Break,5,main]  控制中断监视器
         方法2:线程池的线程:Thread[pool-1-thread-1,5,main]
         方法2:线程池的线程:Thread[pool-1-thread-2,5,main]
         方法2:线程池的线程:Thread[pool-1-thread-3,5,main]
         方法2:线程池的线程:Thread[pool-1-thread-4,5,main]
         方法2:线程池的线程:Thread[pool-1-thread-5,5,main]
         */

    }

    private static void setThreadFactory(ExecutorService executorService,Set<Thread> threadsContainer){
        if (executorService instanceof ThreadPoolExecutor) {
            ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService;
            //获取线程工厂
            ThreadFactory oldThreadFactory = threadPoolExecutor.getThreadFactory();
            //在把线程工程设置到包装类 DelegatingThreadFactory ,再设置回线程池。
            threadPoolExecutor.setThreadFactory(new MyThreadFactory(oldThreadFactory,threadsContainer));
        }

    }
    //我的的线程工厂
    private static class MyThreadFactory implements ThreadFactory {

        private final ThreadFactory threadFactory;
        private final Set<Thread> threadsContainer;

        private MyThreadFactory(ThreadFactory threadFactory, Set<Thread> threadsContainer) {
            this.threadFactory = threadFactory;
            this.threadsContainer = threadsContainer;
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = threadFactory.newThread(r);
            //cache thread 记录线程
            threadsContainer.add(thread);
            //删除不存活的线程
//            threadsContainer.removeIf(next -> !next.isAlive());
            return thread;
        }
    }

}

以上是关于如何获取线程池ThreadPoolExecutor正在运行的线程的主要内容,如果未能解决你的问题,请参考以下文章

ThreadPoolExecutor线程池设计思路

线程池源码分析之ThreadPoolExecutor

ThreadPoolExecutor 的三种提交任务方式

解析ThreadPoolExecutor类是如何保证线程池正确运行的

线程池详解(ThreadPoolExecutor)

解析ThreadPoolExecutor类是如何保证线程池正确运行的