• ThreadGroup


    序言

    java中默认启动就有2个线程组:

    1. system线程组
    2. main线程组

    线程组之间是嵌套的关系,system线程组就嵌套了main线程组.

    我们如果没有给线程指定线程组,则默认是创建在main线程组中的.同理线程池如果没有指定线程组,也是归属在main线程组中的.cuiyaonan2000@163.com

    线程运行中途不能改变它所属的线程组,也就是说线程一旦指定所在的线程组,就直到该线程结束。

    执行如下代码

    1. package nan.yao.cui.test;
    2. import java.util.concurrent.ExecutorService;
    3. import java.util.concurrent.Executors;
    4. import java.util.concurrent.ThreadPoolExecutor;
    5. /**
    6. * @Author: cuiyaonan2000@163.com
    7. * @Description: todo
    8. * @Date: Created at 2022-6-6 9:38
    9. */
    10. public class Test01 implements Runnable{
    11. public static void main(String[] args){
    12. //连接池的代码
    13. ExecutorService newFixThreadPool_1 = Executors.newCachedThreadPool();
    14. newFixThreadPool_1.submit(new Test01());
    15. // System.out.println("自定义的线程组");
    16. // ThreadGroup tg = new ThreadGroup();
    17. //
    18. // new Thread();
    19. // System.out.println();
    20. //
    21. // System.out.println(tg.getParent().getName());
    22. }
    23. public void showThreadGroup(Thread thread){
    24. ThreadGroup threadGroup = thread.getThreadGroup();
    25. do{
    26. System.out.println("线程组的名字是:" + threadGroup.getName() +" 当前的优先级是:" + threadGroup.getMaxPriority());
    27. System.out.println("是否是守护线程组:" + threadGroup.isDaemon() +" 当前线程组的线程数是:" + threadGroup.activeCount());
    28. threadGroup = threadGroup.getParent();
    29. }while(threadGroup != null );
    30. }
    31. @Override
    32. public void run() {
    33. ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
    34. do{
    35. System.out.println("线程组的名字是:" + threadGroup.getName() +" 当前的优先级是:" + threadGroup.getMaxPriority());
    36. System.out.println("是否是守护线程组:" + threadGroup.isDaemon() +" 当前线程组的线程数是:" + threadGroup.activeCount());
    37. threadGroup = threadGroup.getParent();
    38. }while(threadGroup != null );
    39. }
    40. }

    ThreadGroup & ThreadPool

    我们创建的线程必然是要有线程组的,(注意是一定会有线程组cuiyaonan2000@163.com).

    线程组顾名思义就是用于批量管理线程,省去我们为每一个线程设置优先级,异常处理等信息.

    线程池是用于管理线程的生命周期的,从创建,就绪,运行,等待,死亡,超时.另线程池里的线程创建默认也是制定了线程组的,即只要是线程一定会有个线程组.

    Thread Must need ThreadGroup

    为什么我们创建的线程一定会设置线程组的原因?

    Thread

    针对我们创建的线程,以new Thread 为例

    如上Thread的构造方法中,如果要设置ThreadGroup则一定不能为空.

    这里我们看下没有传递ThreadGroup的构造函数.以public Thread() 为例子

     可以看到内部又调用了init()且传递的ThreadGroup为null

    init() 内容如下

    1. /**
    2. * Initializes a Thread.
    3. *
    4. * @param g the Thread group
    5. * @param target the object whose run() method gets called
    6. * @param name the name of the new Thread
    7. * @param stackSize the desired stack size for the new thread, or
    8. * zero to indicate that this parameter is to be ignored.
    9. * @param acc the AccessControlContext to inherit, or
    10. * AccessController.getContext() if null
    11. * @param inheritThreadLocals if {@code true}, inherit initial values for
    12. * inheritable thread-locals from the constructing thread
    13. */
    14. private void init(ThreadGroup g, Runnable target, String name,
    15. long stackSize, AccessControlContext acc,
    16. boolean inheritThreadLocals) {
    17. if (name == null) {
    18. throw new NullPointerException("name cannot be null");
    19. }
    20. this.name = name;
    21. Thread parent = currentThread();
    22. SecurityManager security = System.getSecurityManager();
    23. if (g == null) {
    24. /* Determine if it's an applet or not */
    25. /* If there is a security manager, ask the security manager
    26. what to do. */
    27. if (security != null) {
    28. g = security.getThreadGroup();
    29. }
    30. /* If the security doesn't have a strong opinion of the matter
    31. use the parent thread group. */
    32. if (g == null) {
    33. g = parent.getThreadGroup();
    34. }
    35. }
    36. /* checkAccess regardless of whether or not threadgroup is
    37. explicitly passed in. */
    38. g.checkAccess();
    39. /*
    40. * Do we have the required permissions?
    41. */
    42. if (security != null) {
    43. if (isCCLOverridden(getClass())) {
    44. security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
    45. }
    46. }
    47. g.addUnstarted();
    48. this.group = g;
    49. this.daemon = parent.isDaemon();
    50. this.priority = parent.getPriority();
    51. if (security == null || isCCLOverridden(parent.getClass()))
    52. this.contextClassLoader = parent.getContextClassLoader();
    53. else
    54. this.contextClassLoader = parent.contextClassLoader;
    55. this.inheritedAccessControlContext =
    56. acc != null ? acc : AccessController.getContext();
    57. this.target = target;
    58. setPriority(priority);
    59. if (inheritThreadLocals && parent.inheritableThreadLocals != null)
    60. this.inheritableThreadLocals =
    61. ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    62. /* Stash the specified stack size in case the VM cares */
    63. this.stackSize = stackSize;
    64. /* Set thread ID */
    65. tid = nextThreadID();
    66. }

    如下如果我们没有指定new Thread()的线程组,则默认会使用创建该子线程的线程组,如下图所示(一般为main()线程组)

     

    自定义ThreadGroup

    如上我们可以在创建Thread中设置线程组.那自定义线程组的构造函数如下所示 

    这里主要看下只需要name的构造函数

     由此可见我们创建的线程组一定是 main线程组的子线程组.

    线程池的线程

    以代码如下代码为例:

    1. //连接池的代码
    2. ExecutorService newFixThreadPool_1 = Executors.newCachedThreadPool();
    3. newFixThreadPool_1.submit(new Test01());

    线程池的创建主要是如下的代码产生

    在如下所示,线程池创建的线程所属的线程组是创建线程的线程组

     

     

    ThreadGroup作用范围

    这个很容易理解,就是为线程组的线程设置默认的属性和处理方法.(因为是默认的属性和方法,自定线程当然可以进行覆盖)

    这里距离几种重要的属性和默认方法的设置

    线程优先级

    优先级由1到10之间的整数表示。

    优先级为1的线程优先级最低。优先级为10的线程具有最高优先级。

    在Thread类中定义了三个常量来表示下表中列出的三个不同的线程优先级。

    线程优先级常量整数值
    MIN_PRIORITY1
    NORM_PRIORITY5
    MAX_PRIORITY10

    异常处理

    线程的异常处理有4个level

    1. 针对线程对象的方法setUncaughtExceptionHandler
    2. 针对线程类的静态方法setDefaultUncaughtExceptionHandler
    3. 自定义线程组类对象,重写uncaughtException

    优先级必然是:线程对象设置>线程组对象设置>线程类静态方法设置

    1. package nan.yao.cui.test;
    2. import java.util.concurrent.ExecutorService;
    3. import java.util.concurrent.Executors;
    4. import java.util.concurrent.ThreadPoolExecutor;
    5. /**
    6. * @Author: cuiyaonan2000@163.com
    7. * @Description: todo
    8. * @Date: Created at 2022-6-6 9:38
    9. */
    10. public class Test01 implements Runnable {
    11. public static void main(String[] args) throws InterruptedException {
    12. //针对线程类的静态方法
    13. Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
    14. System.out.println("this is setDefaultUncaughtExceptionHandler .the thread" + t.getName() + " catch the exception:" + e.getMessage());
    15. });
    16. //相当于是集成了ThreadGroup并且重写了uncaughtException 方法
    17. ThreadGroup tg = new ThreadGroup("myTG"){
    18. @Override
    19. public void uncaughtException(Thread t, Throwable e) {
    20. System.out.println( "线程组:" + getName() + "下的线程:"+ t.getName() + "出现了异常:" + e.getMessage());
    21. }
    22. };
    23. //设置线程组的权限
    24. tg.setMaxPriority(Thread.MAX_PRIORITY);
    25. Test01 test01 = new Test01();
    26. Test01 test02 = new Test01();
    27. Test01 test03 = new Test01();
    28. Test01 test04 = new Test01();
    29. Thread t1 = new Thread(tg,test01,"第一个异常");
    30. Thread t2 = new Thread(test01,"第二个异常");
    31. //针对该线程的异常捕获
    32. t2.setUncaughtExceptionHandler((t, e) -> {
    33. System.out.println("this is setUncaughtExceptionHandler .the thread" + t.getName() +" catch the exception:" + e.getMessage());
    34. });
    35. //会使用默认的异常捕获
    36. Thread t3 = new Thread(test03,"第三个异常");
    37. Thread t4 = new Thread(tg,test04,"第四个异常");
    38. t4.setUncaughtExceptionHandler((t, e) -> {
    39. System.out.println("this is setUncaughtExceptionHandler .the thread" + t.getName() +" catch the exception:" + e.getMessage());
    40. });
    41. t1.start();
    42. t2.start();
    43. t3.start();
    44. t4.start();
    45. Thread.sleep(5000);
    46. }
    47. @Override
    48. public void run() {
    49. throw new RuntimeException("this is business exception ,throwed by " + Thread.currentThread().getName());
    50. }
    51. }

  • 相关阅读:
    Jenkins 添加节点Node报错JNI error has occurred UnsupportedClassVersionError
    跟着 Guava 学 Java 之 集合工具类
    一个简单的HTML网页 个人网站设计与实现 HTML+CSS+JavaScript自适应个人相册展示留言博客模板
    Python的pip包管理器介绍和使用
    【Java】三大集合容器概述
    安卓sdk对应表
    ChinaSkills全国职业院校技能大赛Debian样题一||本专栏基于此试题,订阅前必读!!!
    工具分享-Ajax Interceptor
    hutool的HttpRequest.post的使用-包括上传文档等多个传参【总结版本】
    基于敏捷开发的低代码平台建设
  • 原文地址:https://blog.csdn.net/cuiyaonan2000/article/details/125789063