第三章 Java多线程——线程组和线程优先级

3.1 线程组(ThreadGroup)

Java中用ThreadGroup来表示线程组,我们可以使用线程组对线程进行批量控制。
每个Thread必然存在于一个ThreadGroup中,Thread不能独立于ThreadGroup存在。执行main()方法线程的名字是main,如果zainew Thread 时没有显式指定,那么默认父线程(当前执行new Thread的线程) 线程组设置为自己的线程组。

/**
* @author :ls
* @date :Created in 2022/4/19 10:07
* @description:
*/
public class T1 {
    public static void main(String[] args) {
        Thread sub_thread = new Thread(()->{
            System.out.println("sub_thread--->当前线程组名字-                                                                              >"+Thread.currentThread().getThreadGroup().getName());
            System.out.println("sub_thread--->当前线名字-->"+Thread.currentThread().getName());
        });
        sub_thread.start();
        System.out.println("main方法----->"+Thread.currentThread().getName());
    }
}

输出结果:

main方法----->main
sub_thread--->当前线程组名字-->main
sub_thread--->当前线名字-->Thread-0

ThreadGroup管理着它下面的Thread,ThreadGroup是一个标准的向下引用的树状结构,这样设计的原因是防止“上级”线程被“下级”线程引用而无法有效的被GC回收

3.2 线程的优先级

java中线程的优先级默认值是5,可指定范围为:1~10。在这里 java知识给操作系统一个优先级的参考值,线程最终在操作系统的优先级是多少还是由操作系统决定,也就是cpu对线程的调度,不完全是按优先级来执行的。

使用方法 setPriority() 来设定线程的优先级。

public class Demo {
    public static void main(String[] args) {
        Thread a = new Thread();
        System.out.println("我是默认线程优先级:"+a.getPriority());
        Thread b = new Thread();
        b.setPriority(10);
        System.out.println("我是设置过的线程优先级:"+b.getPriority());
    }
}

输出结果:

我是默认线程优先级:5
我是设置过的线程优先级:10

当然这里设置线程的优先级,在实际的业务实现中是不建议采用的!! 首先来说 java线程中的优先级不是特可靠,其次硬件的配置(如 cpu) 不同对于线程执行来说也是有影响的。

public class Demo {
    public static class T1 extends Thread {
        @Override
        public void run() {
            super.run();
            System.out.println(String.format("当前执⾏的线程是:%s,优先级:%d",
                    Thread.currentThread().getName(),
                    Thread.currentThread().getPriority()));
        }
    }
    public static void main(String[] args) {
        IntStream.range(1, 10).forEach(i -> {
            Thread thread = new Thread(new T1());
            thread.setPriority(i);
            thread.start();
        });
    }
}

某次的输出:

当前执⾏的线程是:Thread-17,优先级:9 
当前执⾏的线程是:Thread-1,优先级:1 
当前执⾏的线程是:Thread-13,优先级:7 
当前执⾏的线程是:Thread-11,优先级:6 
当前执⾏的线程是:Thread-15,优先级:8 
当前执⾏的线程是:Thread-7,优先级:4 
当前执⾏的线程是:Thread-9,优先级:5 
当前执⾏的线程是:Thread-3,优先级:2 
当前执⾏的线程是:Thread-5,优先级:3

这个结果 多次执行,结果是不同的。

java 中 有个线程调度器来监视和控制处于RUNNABLE状态的线程。线程的调度策略采用抢占式,优先级高的线程比优先级低的线程有更大几率优先执行。 在优先级相同情况下,按照“先到先得”的原则。每个java程序都有一个默认的主线程,就是通过JVM启动的第一个main线程。

此外,还有一种线程称作:“守护线程 (Daemon)” 守护线程默认优先级比较低

  • 如果某线程是守护线程,那如果所有的非守护线程结束,这个守护线程也会 自动结束。
  • 应用场景是:当所有非守护线程结束时,结束其余的子线程(守护线程)自动关闭,就免去了还要继续关闭⼦线程的麻烦。
  • 应用场景是:当所有非守护线程结束时,结束其余的子线程(守护线程)自动关闭,就免去了还要继续关闭⼦线程的麻烦。

线程与线程组的优先级不同时,将会怎样呢??

public static void main(String[] args) {
    ThreadGroup threadGroup = new ThreadGroup("t1");
    threadGroup.setMaxPriority(6);
    Thread thread = new Thread(threadGroup,"thread");
    thread.setPriority(9);
    System.out.println("我是线程组的优先级"+threadGroup.getMaxPriority());
    System.out.println("我是线程的优先级"+thread.getPriority());
}

输出:

我是线程组的优先级6
我是线程的优先级6

从结果来看,如果线程与所在线程组的优先级发生冲突时,该线程的优先级会失效,以线程组的最大优先级替代。

3.3 线程组的常用方法及数据结构

3.3.1 线程组的常用方法

获取当前线程组的名字:

Thread.currentThread().getThreadGroup().getName()

复制线程组:

Thread[] threads = new Thread[threadGroup.activeCount()];
TheadGroup threadGroup = new ThreadGroup();
threadGroup.enumerate(threads);

线程组 统一异常处理

/**
* @author :ls
* @date :Created in 2022/4/19 10:54
* @description:
*/
public class T2 {
    public static void main(String[] args) {
        ThreadGroup threadGroup = new ThreadGroup("group1"){
            /**
             * 继承ThreadGroup并重新定义一下方法
             * 在线程成员抛出unchecked exception
             * 会执行此方法
             * */
            @Override
            public void uncaughtException(Thread t, Throwable e){
                System.out.println(t.getName()+": "+e.getMessage());
            }
        };


        Thread thread = new Thread(threadGroup,new Runnable() {
            @Override
            public void run() {
                //抛出 unchecked 异常
                throw new RuntimeException("测试异常!!");
            }
        },"mythread");
        thread.start();
    }
}

执行结果:

mythread: 测试异常!!

3.3.1 线程组的数据结构

线程组不仅可以包含线程,也可以包含线程。

ThreadGroup 中的成员变量:

public class ThreadGroup implements Thread.UncaughtExceptionHandler {
    private final ThreadGroup parent; // ⽗亲ThreadGroup
    String name; // ThreadGroupr 的名称
    int maxPriority; // 线程最⼤优先级
    boolean destroyed; // 是否被销毁
    boolean daemon; // 是否守护线程
    boolean vmAllowSuspension; // 是否可以中断
    int nUnstartedThreads = 0; // 还未启动的线程
    int nthreads; // ThreadGroup中线程数⽬
    Thread threads[]; // ThreadGroup中的线程
    int ngroups; // 线程组数⽬
    ThreadGroup groups[]; // 线程组数组
}

构造函数:

// 私有构造函数
private ThreadGroup() {
    this.name = "system";
    this.maxPriority = Thread.MAX_PRIORITY;
    this.parent = null;
}
// 默认是以当前ThreadGroup传⼊作为parent ThreadGroup,新线程组的⽗线程组是⽬前正在运⾏线
public ThreadGroup(String name) {
    this(Thread.currentThread().getThreadGroup(), name);
}
// 构造函数
public ThreadGroup(ThreadGroup parent, String name) {
    this(checkParentAccess(parent), parent, name);
}
// 私有构造函数,主要的构造函数
private ThreadGroup(Void unused, ThreadGroup parent, String name) {
    this.name = name;
    this.maxPriority = parent.maxPriority;
    this.daemon = parent.daemon;
    this.vmAllowSuspension = parent.vmAllowSuspension;
    this.parent = parent;
    parent.add(this);
}

第三个构造函数里调用了 checkParentAccess 方法,这里看看这个方法的源码:

// 检查parent ThreadGroup
private static Void checkParentAccess(ThreadGroup parent) {
    parent.checkAccess();
    return null;
}
// 判断当前运⾏的线程是否具有修改线程组的权限
public final void checkAccess() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkAccess(this);
    }
}
  • 这里涉及到 SecurityManager 这个类,它是Java的安全管理器,它允许应用 程序在执行一个可能不安全或敏感的操作前确定该操作是什么,以及是否是 在允许执行该操作的安全上下文中执行它。应用程序可以允许或不允许该操 作。
  • 比如引入了第三方类库,但是并不能保证它的安全性。
  • 其实Thread类也有一个checkAccess()方法,不过是用来当前运行的线程是 否有权限修改被调用的这个线程实例。(Determines if the currently running thread has permission to modify this thread.)

总结来说,线程组是一个树状的结构,每个线程组下面可以有多个线程或者线程 组。线程组可以起到统一控制线程的优先级和检查线程的权限的作用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值