ThreadGroup解读
我们的项目用到了ThreadGroup 把thread放到了threadGroup中,名称统一起来了;
private static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(, ,
5L, TimeUnit.MINUTES,
new ArrayBlockingQueue<>(), new ThreadFactory() { private final ThreadGroup threadGroup = new ThreadGroup("fileTemplateMethodThreadGroup"); private final AtomicInteger threadNumber = new AtomicInteger(); @Override
public Thread newThread(Runnable r) {
return new Thread(threadGroup, r, "fileTemplateMethod-thread-pool-" + threadNumber.getAndIncrement());
}
}, (r, executor) -> {
if (!executor.isShutdown()) {
/* 丢弃队列最老的数据 */
if (executor.getQueue().poll() != null) {
Cat.logMetricForCount(CatConstant.METRIC_DISCARD_FILE_TASK_COUNT);
}
executor.execute(r);
}
});
ThreadGroup 可以把thread的名字统一起来。一起处理catch。
ThreadGroup是Java提供的一种对线程进行分组管理的手段,可以对所有线程以组为单位进行操作,如设置优先级、守护线程等。
线程组也有父子的概念,如下图:
线程组的创建
public class ThreadGroupCreator { public static void main(String[] args) {
//获取当前线程的group
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
//在当前线程执行流中新建一个Group1
ThreadGroup group1 = new ThreadGroup("Group1");
//Group1的父线程,就是main线程所在Group
System.out.println(group1.getParent() == currentGroup);
//定义Group2, 指定group1为其父线程
ThreadGroup group2 = new ThreadGroup(group1, "Group2");
System.out.println(group2.getParent() == group1);
}
}
ThreadGroup是位于java.lang包下的一个类,用于统一的线程管理.一旦一个线程加入到一个线程组后,就不能更换线程所在的线程组
将当前线程加入到线程组中
public class ThreadGroupCreator { public static void main(String[] args) {
//获取当前线程的group
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
//在当前线程执行流中新建一个Group1
ThreadGroup group1 = new ThreadGroup("Group1");
//Group1的父线程,就是main线程所在Group
System.out.println(group1.getParent() == currentGroup);
//定义Group2, 指定group1为其父线程
ThreadGroup group2 = new ThreadGroup(group1, "Group2");
System.out.println(group2.getParent() == group1);
}
}
将ThreadGroup中活跃的线程引用复制到线程组
Thread[] threads = new Thread[num];
threadGroup.enumerate(threads);
for (Thread t : threads) {
System.out.println("线程名-" + t.getName());
}
测试源代码如下
public class MyThread implements Runnable { @Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " -> start");
TimeUnit.SECONDS.sleep();
//随机发生异常
if (ThreadLocalRandom.current().nextInt() > ) {
throw new RuntimeException(Thread.currentThread().getName() + "发生异常");
}
System.out.println(Thread.currentThread().getName() + " -> end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public class ThreadGroupTest {
public static void main(String[] args) {
int num = ;
ThreadGroup threadGroup = new ThreadGroup("test-group") {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("ThreadGroup捕获到线程异常 - " + e.getMessage());
}
}; List<Thread> threadList = new ArrayList<>();
for (int i = ; i < num; i++) {
Thread thread = new Thread(threadGroup, new MyThread(), "threadname-" + i);
threadList.add(thread);
} System.out.println("运行前线程组中活跃线程数 -> " + threadGroup.activeCount());
System.out.println("开始运行所有线程...");
for (Thread t : threadList) {
t.start();
}
//获取线程组中所有[活动]线程
Thread[] threads = new Thread[num];
threadGroup.enumerate(threads);
for (Thread t : threads) {
System.out.println("线程名-" + t.getName());
}
System.out.println("所有线程运行后,线程组中活跃线程数-" + threadGroup.activeCount());
//不断的查看线程组中活跃的线程数
Thread thread = new Thread(() -> {
int num1;
try {
while ((num1 = threadGroup.activeCount()) > ) {
System.out.println("当前线程组活跃线程数为 -> " + num1);
TimeUnit.SECONDS.sleep();
}
System.out.println("All Thread HAS FINISHED");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
}
}
运行结果如下
运行前线程组中活跃线程数 -> 0
开始运行所有线程...
threadname- -> start
threadname- -> start
threadname- -> start
threadname- -> start
threadname- -> start
threadname- -> start
threadname- -> start
threadname- -> start
threadname- -> start
线程名-threadname-
threadname- -> start
线程名-threadname-
线程名-threadname-
线程名-threadname-
线程名-threadname-
线程名-threadname-
线程名-threadname-
线程名-threadname-
线程名-threadname-
线程名-threadname-
所有线程运行后,线程组中活跃线程数-
当前线程组活跃线程数为 ->
当前线程组活跃线程数为 ->
当前线程组活跃线程数为 ->
当前线程组活跃线程数为 ->
当前线程组活跃线程数为 ->
当前线程组活跃线程数为 ->
当前线程组活跃线程数为 ->
当前线程组活跃线程数为 ->
当前线程组活跃线程数为 ->
当前线程组活跃线程数为 ->
threadname- -> end
threadname- -> end
ThreadGroup捕获到线程异常 - threadname-7发生异常
ThreadGroup捕获到线程异常 - threadname-2发生异常
threadname- -> end
ThreadGroup捕获到线程异常 - threadname-3发生异常
ThreadGroup捕获到线程异常 - threadname-9发生异常
ThreadGroup捕获到线程异常 - threadname-1发生异常
threadname- -> end
threadname- -> end
All Thread HAS FINISHED
---------------------
线程组的基本操作
注意:后添加进线程组的线程,其优先级不能大于线程组的优先级
public class ThreadGroupBasic { public static void main(String[] args) throws InterruptedException { ThreadGroup group = new ThreadGroup("group1");
Thread thread = new Thread(group, () -> {
while(true) {
try {
TimeUnit.SECONDS.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "thread");
thread.setDaemon(true);
thread.start(); TimeUnit.MILLISECONDS.sleep(); ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
//递归获取mainGroup中活跃线程的估计值
System.out.println("activeCount = " + mainGroup.activeCount());
//递归获mainGroup中的活跃子group
System.out.println("activeGroupCount = " + mainGroup.activeGroupCount());
//获取group的优先级, 默认为10
System.out.println("getMaxPriority = " + mainGroup.getMaxPriority());
//获取group的名字
System.out.println("getName = " + mainGroup.getName());
//获取group的父group, 如不存在则返回null
System.out.println("getParent = " + mainGroup.getParent());
//活跃线程信息全部输出到控制台
mainGroup.list();
System.out.println("----------------------------");
//判断当前group是不是给定group的父线程, 如果两者一样,也会返回true
System.out.println("parentOf = " + mainGroup.parentOf(group));
System.out.println("parentOf = " + mainGroup.parentOf(mainGroup)); } }
线程组的Interrupt
public class ThreadGroupInterrupt { public static void main(String[] args) throws InterruptedException {
ThreadGroup group = new ThreadGroup("TestGroup");
new Thread(group, () -> {
while(true) {
try {
TimeUnit.MILLISECONDS.sleep();
} catch (InterruptedException e) {
//received interrupt signal and clear quickly
System.out.println(Thread.currentThread().isInterrupted());
break;
}
}
System.out.println("t1 will exit");
}, "t1").start();
new Thread(group, () -> {
while(true) {
try {
TimeUnit.MILLISECONDS.sleep();
} catch (InterruptedException e) {
//received interrupt signal and clear quickly
System.out.println(Thread.currentThread().isInterrupted());
break;
}
}
System.out.println("t2 will exit");
}, "t2").start();
//make sure all threads start
TimeUnit.MILLISECONDS.sleep(); group.interrupt();
} }
线程组的destroy
public class ThreadGroupDestroy { public static void main(String[] args) {
ThreadGroup group = new ThreadGroup("TestGroup");
ThreadGroup mainGroup = Thread.currentThread().getThreadGroup();
//before destroy
System.out.println("group.isDestroyed=" + group.isDestroyed());
mainGroup.list(); group.destroy();
//after destroy
System.out.println("group.isDestroyed=" + group.isDestroyed());
mainGroup.list();
} }
线程组设置守护线程组
线程组设置为守护线程组,并不会影响其线程是否为守护线程,仅仅表示当它内部没有active的线程的时候,会自动destroy
public class ThreadGroupDaemon { public static void main(String[] args) throws InterruptedException {
ThreadGroup group1 = new ThreadGroup("group1");
new Thread(group1, () -> {
try {
TimeUnit.SECONDS.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "group1-thread1").start();
ThreadGroup group2 = new ThreadGroup("group2");
new Thread(group2, () -> {
try {
TimeUnit.SECONDS.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "group1-thread2").start();
group2.setDaemon(true); TimeUnit.SECONDS.sleep();
System.out.println(group1.isDestroyed());
System.out.println(group2.isDestroyed());
}
}
ThreadGroup解读的更多相关文章
- java.lang.Thread、java.lang.ThreadGroup和java.lang.ThreadLocal<T>详细解读
一.Thread类 public class Thread extends Object impments Runnable 线程是程序中的 执行线程.java虚拟机允许应用程序并发地运行多个执行线 ...
- JVM源码分析之堆外内存完全解读
JVM源码分析之堆外内存完全解读 寒泉子 2016-01-15 17:26:16 浏览6837 评论0 阿里技术协会 摘要: 概述 广义的堆外内存 说到堆外内存,那大家肯定想到堆内内存,这也是我们 ...
- 对threading模块源码文件的解读(不全)
# -*- coding: utf-8 -*- #python 27 #xiaodeng #对threading模块源码文件的解读(不全) import threading #类 #Thread() ...
- SDWebImage源码解读之SDWebImageDownloaderOperation
第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
- SDWebImage源码解读 之 NSData+ImageContentType
第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...
- SDWebImage源码解读 之 UIImage+GIF
第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...
- SDWebImage源码解读 之 SDWebImageCompat
第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...
- SDWebImage源码解读_之SDWebImageDecoder
第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...
- SDWebImage源码解读之SDWebImageCache(上)
第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...
随机推荐
- Java中string.equalsIgnoreCase("0")与"0".equalsIgnoreCase(string)的区别:
string.equalsIgnoreCase("0"):如果string为null,会抛出java.lang.NullPointerException异常. "0&qu ...
- 关于Skyline沿对象画boundingbox的探讨
先来说说为什么要搞这个?项目中经常遇到的一个操作就是选定对象,以前都是通过Tint设置对象颜色来标识选定对象,但是随着图层中模型增多,模型色彩丰富,会出现选定色与对象颜色对比不明显的情况.因为看到Te ...
- Python开发爬虫之BeautifulSoup解析网页篇:爬取安居客网站上北京二手房数据
目标:爬取安居客网站上前10页北京二手房的数据,包括二手房源的名称.价格.几室几厅.大小.建造年份.联系人.地址.标签等. 网址为:https://beijing.anjuke.com/sale/ B ...
- Rxjs常用operators
本文使用的是angular6内置的rxjs,版本号为6.3.3 concat 通过顺序地发出多个 Observables 的值将它们连接起来,一个接一个的. 参数: 名称 类型 属性 描述 other ...
- Python 使用Python远程连接并操作InfluxDB数据库
使用Python远程连接并操作InfluxDB数据库 by:授客 QQ:1033553122 实践环境 Python 3.4.0 CentOS 6 64位(内核版本2.6.32-642.el6.x86 ...
- C#监控指定目录的文件变化的代码
如下的资料是关于C#监控指定目录的文件变化的代码. FileSystemWatcher watcher = new FileSystemWatcher();watcher.Path = @" ...
- python爬虫实战:利用scrapy,短短50行代码下载整站短视频
近日,有朋友向我求助一件小事儿,他在一个短视频app上看到一个好玩儿的段子,想下载下来,可死活找不到下载的方法.这忙我得帮,少不得就抓包分析了一下这个app,找到了视频的下载链接,帮他解决了这个小问题 ...
- GitHub和75亿美金
如果你是看到了75亿进来的,还在纳闷前面那个github的是个什么,你可以走人了?如果你进来是想看到微软两个字的,请继续. 微软以75亿美金的股票收购Github这件事情,从周六一早我爬山到香山琉璃塔 ...
- SQLServer之修改表值函数
修改表值函数注意事项 更改先前通过执行 CREATE FUNCTION 语句创建的现有 Transact-SQL 或 CLR 函数,但不更改权限,也不影响任何相关的函数.存储过程或触发器. 不能用 A ...
- man -f/-k [keyword]在fedora 29 中报错nothing appropriate
我们在使用 man 手册的时候,可以使用man -f [keyword]去查询keyword的在线文档,但是这时候会报错:(图来源自网络) 这是因为我们还没有建立 man 手册的索引缓存: 我们可以使 ...