橘子学JDK之线程组

一、简介

我们以前一直说线程,但是其实线程有这么一个构造函数,我们看一下。

public Thread(ThreadGroup group, Runnable target, String name) {
    init(group, target, name, 0);
}

我们看到第一个参数是分组,其实就是线程组,这里引出线程组的概念,也就是说我们能给那些线程分组,使得多个线程处于一个组下面,方便管理。我们来看看线程组的一个结构图。
在这里插入图片描述
我们看到他是个树状的结构,而且每个下面都可以有线程和线程组,我没画全,其实是还能有很多层,每个节点下面都能有。
这就是线程组的一个结构,我们来看下代码、

二、线程组的源码

1、构造方法

public Thread(ThreadGroup group, Runnable target, String name) {
     init(group, target, name, 0);
 }

我们点进去init这个方法。

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();
}

到这里我们基本知道了这个线程组的一个设计。你指定了就是你指定的,没指定就按父线程的线程组进行处理。

2、代码操作

package com.lyx.thread;

import java.util.concurrent.TimeUnit;

/**
 * @author: levi
 * @description: TODO
 * @date: 2022-10-10 21:10
 * @version: 1.0
 */
public class ThreadGroupApi {
    public static void main(String[] args) {
        // 1号线程组
        ThreadGroup group1 = new ThreadGroup("group1");
        // 2号线程组,但是2号线程组属于1号线程组,我把线程组1作为参数传进去
        ThreadGroup group2 = new ThreadGroup(group1,"group2");

        // t11属于线程组1
        Thread t11 = new Thread(group1,()->{
            System.out.println(Thread.currentThread().getName() + "is running...");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t11");

        // t12属于线程组1
        Thread t12 = new Thread(group1,()->{
            System.out.println(Thread.currentThread().getName() + "is running...");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t12");

        // t13属于线程组1
        Thread t13 = new Thread(group1,()->{
            System.out.println(Thread.currentThread().getName() + "is running...");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t13");

        // t14不指定线程组
        Thread t14 = new Thread(()->{
            System.out.println(Thread.currentThread().getName() + "is running...");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t14");

        // t21属于线程组2
        Thread t21 = new Thread(group2,()->{
            System.out.println(Thread.currentThread().getName() + "is running...");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t21");

        // t22属于线程组2
        Thread t22 = new Thread(group2,()->{
            System.out.println(Thread.currentThread().getName() + "is running...");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t22");

        t11.start();
        t12.start();
        t13.start();
        //t14.start();
        t21.start();
        t22.start();

        System.out.println("t11所属线程组为:" + t11.getThreadGroup().getName());
        System.out.println("t12所属线程组为:" + t12.getThreadGroup().getName());
        System.out.println("t13所属线程组为:" + t13.getThreadGroup().getName());
        System.out.println("t14所属线程组为:" + t14.getThreadGroup().getName());
        System.out.println("t21所属线程组为:" + t21.getThreadGroup().getName());
        System.out.println("t22所属线程组为:" + t22.getThreadGroup().getName());
        System.out.println("main线程所属线程组为:" + Thread.currentThread().getThreadGroup().getName());
        System.out.println("1号线程组里面活跃的线程个数为:" + t11.getThreadGroup().activeCount());
        System.out.println("1号线程组里面活跃的线程组个数为:" + t11.getThreadGroup().activeGroupCount());
 System.out.println("main线程组里面活跃的线程个数为:" + Thread.currentThread().getThreadGroup().activeCount());
        System.out.println("main线程组里面活跃的线程组个数为:" + Thread.currentThread().getThreadGroup().activeGroupCount());

    }
}
 1号线程组
2号线程组,但是2号线程组属于1号线程组,我把线程组1作为参数传进去
t11属于线程组1
t12属于线程组1
t13属于线程组1
t14不指定线程组
t21属于线程组2
t22属于线程组2
t11.start();
t12.start();
t13.start();
//t14.start();
t21.start();
t22.start();

经过上面的描述我们基本可以得到一个关系图如下:
在这里插入图片描述
所以我们看下运行结果是不是能对的上:

t13is running...
t12is running...
t11所属线程组为:group1
t11is running...
t12所属线程组为:group1
t22is running...
t13所属线程组为:group1
t21is running...
t14所属线程组为:main  t14没指定所以是父线程组,t14在主线程开的线程,所以父线程就是main
t21所属线程组为:group2
t22所属线程组为:group2
main线程所属线程组为:main  
1号线程组里面活跃的线程个数为:5 1号线程组里面有五个启动的,要是有一个没start就会少一个
1号线程组里面活跃的线程组个数为:1

main线程组里面活跃的线程个数为:6  我们启动了五个线程,包括主线程是6个
main线程组里面活跃的线程组个数为:2

本文未完待续。。。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值