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.线程组示例:
展示线程组结构代码实例如下:
/**
* 类功能描述:
*
* @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();
}
}
打印结果如下:
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实现代码如下:
/**
* 多线程获取报表数据
* @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
}
统一捕获异常的线程组定义如下:
/**
* 定义报表生成线程组
*
* @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()
}
}