如何獲取線程池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;
}
}
}