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(上)
第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...
随机推荐
- redis分布式锁工具类
目录 (1)需要导入的包 (2)JedisUtil类 (3)jedisPool配置 (4)使用举例 (1)需要导入的包 <dependency> <groupId>redis. ...
- 质量:“PM,你怎么可以放弃我?!”
最近遇到一件有趣的事儿,一位文玩老友为了攒一串多宝,新得几颗高品松石,开心不已与我们分享.闲扯中,他说出了攒多宝的要求: 直径偏差2mm以内 每种品类的珠子都要是高品 品类只能是南红(满色满肉).蜜蜡 ...
- Maven的基础了解与使用
目录 Maven的介绍: 什么是Maven: 为什么要学习maven? 安装与配置: 下载: 配置环境变量 测试安装结果: Maven概念: 坐标 仓库 入门示例 创建maven工程: 添加依赖 Ma ...
- win10系统电脑常用基本操作快捷键
win:开始 == ctrl + ESC :开始菜单 win + X: 开始菜单 win + i : 控制面板 win + L:快速锁屏 win +A:操作中心 win+Tab 时间轴(1803版本 ...
- Python函数二(函数名,闭包,迭代器)之杵臼之交
函数名的使用: 函数名可以作为值,赋值给变量. 函数名可以作为参数传参给函数. 函数名可以作为返回值. 函数名可以作为元素存储在容器里. 闭包:在嵌套函数内,使用外层局部变量(非全局变量)就是一个闭包 ...
- June. 24th 2018, Week 26th. Sunday
Beautiful things don't ask for attention. 真正美丽的东西,并不会刻意寻求别人的注目. From The Secret Life of Walter Mitty ...
- python打印电脑串口的信息
# -*- coding:utf-8 -*- from serial.tools.list_ports import comports port_list = list(comports()) if ...
- django-debug-toolbar使用指南
好久没发新博客,凑个数... django-debug-toolbar 介绍 django-debug-toolbar 是一组可配置的面板,可显示有关当前请求/响应的各种调试信息,并在单击时显示有关面 ...
- 【转】Android 增,删,改,查 通讯录中的联系人
一.权限 操作通讯录必须在AndroidManifest.xml中先添加2个权限, <uses-permission android:name="android.permission. ...
- AI adanet
adanet是一个基于Tensorflow的轻量级框架,只需要很少的专业干预,就可以自动学习出高质量的模型.在最近的AutoML成果上构建,既快速又灵活,还可以保证学习质量. adanet提供通用框架 ...