您当前的位置: 首页 > 

cuiyaonan2000

暂无认证

  • 3浏览

    0关注

    248博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

ThreadGroup

cuiyaonan2000 发布时间:2022-07-18 14:27:36 ,浏览量:3

序言

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

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

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

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

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

执行如下代码

package nan.yao.cui.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author: cuiyaonan2000@163.com
 * @Description: todo
 * @Date: Created at 2022-6-6  9:38
 */
public class Test01 implements Runnable{

    public static void main(String[] args){

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


//        System.out.println("自定义的线程组");
//        ThreadGroup tg = new ThreadGroup();
//
//        new Thread();
//        System.out.println();
//
//        System.out.println(tg.getParent().getName());



    }

    public void showThreadGroup(Thread thread){

        ThreadGroup threadGroup = thread.getThreadGroup();

        do{
            System.out.println("线程组的名字是:" + threadGroup.getName() +" 当前的优先级是:" + threadGroup.getMaxPriority());
            System.out.println("是否是守护线程组:" + threadGroup.isDaemon() +" 当前线程组的线程数是:" + threadGroup.activeCount());
            threadGroup = threadGroup.getParent();
        }while(threadGroup != null );
    }

    @Override
    public void run() {
        ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();

        do{
            System.out.println("线程组的名字是:" + threadGroup.getName() +" 当前的优先级是:" + threadGroup.getMaxPriority());
            System.out.println("是否是守护线程组:" + threadGroup.isDaemon() +" 当前线程组的线程数是:" + threadGroup.activeCount());
            threadGroup = threadGroup.getParent();
        }while(threadGroup != null );
    }
}

ThreadGroup & ThreadPool

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

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

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

Thread Must need ThreadGroup

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

Thread

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

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

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

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

init() 内容如下

/**
     * Initializes a Thread.
     *
     * @param g the Thread group
     * @param target the object whose run() method gets called
     * @param name the name of the new Thread
     * @param stackSize the desired stack size for the new thread, or
     *        zero to indicate that this parameter is to be ignored.
     * @param acc the AccessControlContext to inherit, or
     *            AccessController.getContext() if null
     * @param inheritThreadLocals if {@code true}, inherit initial values for
     *            inheritable thread-locals from the constructing thread
     */
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name;

        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */

            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {
                g = security.getThreadGroup();
            }

            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

        /* checkAccess regardless of whether or not threadgroup is
           explicitly passed in. */
        g.checkAccess();

        /*
         * Do we have the required permissions?
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

        g.addUnstarted();

        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }

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

 

自定义ThreadGroup

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

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

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

线程池的线程

以代码如下代码为例:

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

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

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

 

 

ThreadGroup作用范围

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

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

线程优先级

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

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

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

线程优先级常量整数值MIN_PRIORITY1NORM_PRIORITY5MAX_PRIORITY10

异常处理

线程的异常处理有4个level

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

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

package nan.yao.cui.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author: cuiyaonan2000@163.com
 * @Description: todo
 * @Date: Created at 2022-6-6  9:38
 */
public class Test01 implements Runnable {

    public static void main(String[] args) throws InterruptedException {

        //针对线程类的静态方法
        Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
            System.out.println("this is setDefaultUncaughtExceptionHandler .the thread" + t.getName() + " catch the exception:" + e.getMessage());
        });


        //相当于是集成了ThreadGroup并且重写了uncaughtException 方法
        ThreadGroup tg = new ThreadGroup("myTG"){
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println( "线程组:" + getName() + "下的线程:"+ t.getName() + "出现了异常:" + e.getMessage());
            }
        };
        //设置线程组的权限
        tg.setMaxPriority(Thread.MAX_PRIORITY);


        Test01 test01 = new Test01();
        Test01 test02 = new Test01();
        Test01 test03 = new Test01();
        Test01 test04 = new Test01();


        Thread t1 = new Thread(tg,test01,"第一个异常");
        Thread t2 = new Thread(test01,"第二个异常");


        //针对该线程的异常捕获
        t2.setUncaughtExceptionHandler((t, e) -> {
            System.out.println("this is setUncaughtExceptionHandler .the thread" + t.getName() +" catch the exception:" + e.getMessage());
        });

        //会使用默认的异常捕获
        Thread t3 = new Thread(test03,"第三个异常");

        Thread t4 = new Thread(tg,test04,"第四个异常");
        t4.setUncaughtExceptionHandler((t, e) -> {
            System.out.println("this is setUncaughtExceptionHandler .the thread" + t.getName() +" catch the exception:" + e.getMessage());
        });


        t1.start();
        t2.start();
        t3.start();
        t4.start();


        Thread.sleep(5000);
    }


    @Override
    public void run() {
        throw new RuntimeException("this is business exception ,throwed by " + Thread.currentThread().getName());
    }
}

关注
打赏
1638267374
查看更多评论
立即登录/注册

微信扫码登录

0.0394s