Java线程组(ThreadGroup)使用
JDK 对线程组类注释:
A thread group represents a set of threads. In addition, a thread group can also include other thread groups. The thread groups form a tree in which every thread group except the initial thread group has a parent.
A thread is allowed to access information about its own thread group, but not to access information about its thread group's parent thread group or any other thread groups.
可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式,如图所示.
线程组的作用是:可以批量管理线程或线程组对象,有效地对线程或线程组对象进行组织
1.线程组示例:
展示线程组结构代码实例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /** * 类功能描述: * * @author WangXueXing create at 18-12-27 下午3:25 * @version 1.0.0 */ public class ThreadGroupTest implements Runnable { @Override public void run() { try { while (!Thread.currentThread().isInterrupted()) { Thread currentThread = Thread.currentThread(); System.out.println( "current thread:" + currentThread.getName() + " thread group:" +currentThread.getThreadGroup().getName() + " parent thread group:" +currentThread.getThreadGroup().getParent().getName()); Thread.sleep( 3000 ); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { ThreadGroup rootThreadGroup = new ThreadGroup( "root线程组1" ); Thread t0 = new Thread(rootThreadGroup, new ThreadGroupTest(), "Thread 0" ); t0.start(); ThreadGroup tg = new ThreadGroup(rootThreadGroup, "线程组1" ); ThreadGroup tg2 = new ThreadGroup(rootThreadGroup, "线程组2" ); Thread t1 = new Thread(tg, new ThreadGroupTest(), "Thread 1" ); Thread t2 = new Thread(tg, new ThreadGroupTest(), "Thread 2" ); t1.start(); t2.start(); Thread t3 = new Thread(tg2, new ThreadGroupTest(), "Thread 3" ); Thread t4 = new Thread(tg2, new ThreadGroupTest(), "Thread 4" ); t3.start(); t4.start(); } } |
打印结果如下:
1 2 3 4 5 6 7 8 9 10 | current thread:Thread 0 thread group:root线程组 1 parent thread group:main current thread:Thread 2 thread group:线程组 1 parent thread group:root线程组 1 current thread:Thread 1 thread group:线程组 1 parent thread group:root线程组 1 current thread:Thread 3 thread group:线程组 2 parent thread group:root线程组 1 current thread:Thread 4 thread group:线程组 2 parent thread group:root线程组 1 current thread:Thread 1 thread group:线程组 1 parent thread group:root线程组 1 current thread:Thread 0 thread group:root线程组 1 parent thread group:main current thread:Thread 2 thread group:线程组 1 parent thread group:root线程组 1 current thread:Thread 3 thread group:线程组 2 parent thread group:root线程组 1 ...... |
2.线程组项目中应用(线程组内的线程异常统一管理):
最近有个需求,生成复杂报表-从很多表数据中分析统计到一个报表。
实现思路:
多个线程分别到不同表中查数据并统计分析,任何一个线程失败整体报表生成失败,记录日志并立即中断其他线程。全部线程成功,报表生成成功。
废话少说以下利用Java线程组结合CountDownLatch实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | /** * 多线程获取报表数据 * @param reportId 报表ID * @return */ def getReportData(reportId: Long, supplierDetailMap: ConcurrentHashMap[Integer, Supplier]): ConcurrentHashMap[Integer, AnyRef] = { val dataMap = new ConcurrentHashMap[Integer, AnyRef]() //多线程同步器 val conutDownLatch = new CountDownLatch( 3 ) //实例化线程组 val genThreadGroup = new GenThreadGroup(request.reportInfo.reportType.name, reportId) //获取当月已开返利 new Thread(genThreadGroup, new Runnable { override def run(): Unit = { dataMap.put(OPENED_REBATE_CODE, SupplierAccountDetailQuerySql.getTaxDiscountByMonth(request)) conutDownLatch.countDown() } }, "获取当月已开返利" ).start() //获取当月累计解押款 new Thread(genThreadGroup, new Runnable { override def run(): Unit = { dataMap.put(DEPOSIT_BY_MONTH, SupplierAccountDetailQuerySql.getDepositAmountByMonth(request)) conutDownLatch.countDown() } }, "获取当月累计解押款" ).start() //结算单的含税金额 new Thread(genThreadGroup, new Runnable { override def run(): Unit = { dataMap.put(ACCOUNT_PAYABLE_AMOUNT, SupplierAccountDetailQuerySql.getAccountPayableAmount(request)) conutDownLatch.countDown() } }, "获取结算单的含税金额" ).start() //所有线程都执行完成 conutDownLatch.await() dataMap } |
统一捕获异常的线程组定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /** * 定义报表生成线程组 * * @author BarryWang create at 2018/5/21 11:04 * @version 0.0.1 */ class GenThreadGroup(groupName: String, reportId: Long) extends ThreadGroup(groupName){ val logger: Logger = LoggerFactory.getLogger(classOf[GenThreadGroup]) /** * 定义线程组中任意一个线程异常处理 * @param thread 当前线程 * @param exception 异常 */ override def uncaughtException(thread: Thread, exception: Throwable): Unit = { logger.error(s "报表(ID:${reportId})生成异常, 线程组:${groupName}; 线程:${thread.getName} 失败" , exception) thread.getThreadGroup.interrupt() } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决