写点什么

话说 用户线程 & 守护线程 & 线程组 & 线程优先级

发布于: 2021 年 04 月 05 日
话说  用户线程&守护线程&线程组&线程优先级

如果把公司比喻成进程,


那么你和我就是用户线程,


后勤部门就是守护线程(负责给你订水,打扫办公环境等),


每个项目组就是一个线程组,


程序员等级就是优先级(高级程序员 总比初级程序员容易获取资源 概率大 但不是肯定)。

一、 用户线程 &守护线程
public static void main(String[] args)   {        Thread t = new Thread(() -> {            for (int i = 0; i < 10; i++) {                try {                    Thread.sleep(1000);                    System.out.println("用户线程");                } catch (Exception e) {                    e.printStackTrace();                }            }        });
Thread tdeamon = new Thread(() -> { for (int i = 0; i < 100; i++) { try { Thread.sleep(1000); System.out.println("守护线程"); } catch (Exception e) { e.printStackTrace(); } } }); // 设置线程为守护线程 !!必须在start之前设置 否则会报错 tdeamon.setDaemon(true);
t.start(); tdeamon.start(); }
复制代码


可以复制执行一下看看,t 结束之后,tdeamon 虽然没运行够 100 次但是也就结束了


公司都没有研发、销售、市场等职位了,后勤也就没有必要留着了。


那 new Thread() 默认是守护线程还是用户线程 ?


答案: 不确定,要看父线程 新 new 的线程 默认与父线程一致


1 我们看一下 main 线程的类型


public class TestDeamon08 {    public static void main(String[] args)   {        System.out.println(Thread.currentThread().isDaemon() ? "守护线程":"用户线程");    }}// 输出: 用户线程
复制代码


2 我们看一下 main 线程中新建的线程


public static void main(String[] args)   {        Thread t = new Thread();        System.out.println(t.isDaemon() ? "t=守护线程":"t=用户线程");}// 输出 t=用户线程
复制代码


3 我们看一下 main 线程中的线程中的线程


public static void main(String[] args)   {    new Thread(()->{        Thread t2 = new Thread();        System.out.println(t2.isDaemon() ? "t2= 守护线程":"t2=用户线程");    }).start();}输出: t2= 用户线程
复制代码


4 我们定义一个 deamon 线程 然后在这个线程中新建一个线程看看 新建的这个线程是不是与父线程一致


public static void main(String[] args) throws InterruptedException {    Thread thread = new Thread(() -> {        System.out.println(Thread.currentThread().isDaemon()?                            "thread= 守护线程" : "thread=用户线程");        Thread t3 = new Thread();        System.out.println(t3.isDaemon() ? "t3= 守护线程" : "t3=用户线程");    });    thread.setDaemon(true);    thread.start();

Thread.sleep(10000);}
// 输出:thread= 守护线程t3= 守护线程
复制代码


5 我们看看新建线程是怎么默认 daemon 的


// 创建线程Thread thread = new Thread();// 构造函数  默认名字:Thread-xxx// 调用init public Thread() {        init(null, null, "Thread-" + nextThreadNum(), 0);}// 下边说的线程组ThreadGroupprivate void init(ThreadGroup g, Runnable target, String name,                      long stackSize) {        init(g, target, name, stackSize, null, true);}// 主要逻辑private void init(ThreadGroup g, Runnable target, String name,                      long stackSize, AccessControlContext acc,                      boolean inheritThreadLocals) {    // 线程名字为null 抛异常杨     if (name == null) {        throw new NullPointerException("name cannot be null");    }  // 设置线程名称     this.name = name;  // 获取父线程     Thread parent = currentThread();    //     SecurityManager security = System.getSecurityManager();    // 如果线程分组是null  初始化group     // 如果security != null security.getThreadGroup()    // 如果security == null 就获取父线程的getThreadGroup()    if (g == null) {        if (security != null) {            g = security.getThreadGroup();        }        if (g == null) {            g = parent.getThreadGroup();        }    }
// 一堆代码... // 设置分组 this.group = g; // 设置daemon为父daemon !!! this.daemon = parent.isDaemon(); // 设置优先级为父优先级 this.priority = parent.getPriority(); // 一堆代码...}
复制代码
二、 线程组

在上边代码中我们看到,线程的默认分组是通过 security 获取的,如果 security 为 null 就是用父线程的分组。


1. 我们看看 main 线程的线程组


public static void main(String[] args) throws InterruptedException {    System.out.println("main线程组:"+ Thread.currentThread().getThreadGroup().getName());}输出: main线程组:main
复制代码


2. main 线程中创建线程 默认分组


public static void main(String[] args)  {    new Thread(()->{        System.out.println("线程组:"+Thread.currentThread().getThreadGroup().getName());    }).start();}// 输出:  线程组:main
复制代码


3. 指定线程分组


public static void main(String[] args)  {    ThreadGroup t = new ThreadGroup("分组01");    Thread thread = new Thread(t,()->{        System.out.println("线程组:"+                           Thread.currentThread().getThreadGroup().getName());    });    thread.start();}// 输出: 线程组:分组01
复制代码


4. 指定线程分组 线程中创建线程


public static void main(String[] args)  {    ThreadGroup t = new ThreadGroup("分组01");    Thread thread = new Thread(t,()->{        new Thread(()->{            System.out.println("线程组:"+                               Thread.currentThread().getThreadGroup().getName());        }).start();    });    thread.start();}// 输出: 线程组:分组01
复制代码


5. 线程组作用


首先 他们表示线程所属 , 比如你操作一个线程的时候,如果他是 main 线程组的你就过滤掉


期次线程组提供了一些方法来批量操作线程:


    public static void main(String[] args)  {        ThreadGroup g = new ThreadGroup("分组01");        Thread thread1= new Thread(g,()->{            try {                Thread.sleep(100000);            } catch (Exception e) {                System.out.println("线程1异常 结束:"+e.getMessage());            }        });        Thread thread2= new Thread(g,()->{            try {                Thread.sleep(100000);            } catch (Exception e) {                System.out.println("线程2异常 结束:"+e.getMessage());            }        });
thread1.start(); thread2.start();
// 停止所有线程 // g.stop(); // 终端所有线程 // g.interrupt(); // 还处于活动状态的线程总数 //System.out.println( g.activeCount()); // 输出线程组包含线程信息 //g.list(); // 获取线程组所有线程的最大优先级 //int max = g.getMaxPriority(); // 还有一些其他的 读者阔以自己去看看 了解为主 }
复制代码
三、 优先级

在”一“中我们看源码的时候看到了,优先级默认是获取的父线程的优先级 ,


那 main 线程优先级是多少呢


public static void main(String[] args) {    int pro = Thread.currentThread().getPriority();    System.out.println(pro);}// 输出结果: 5 
复制代码


最大优先级和最小优先级呢 ?


Thread t = new Thread();t.setPriority(10);// 看一下setPriority的时候 限制就行了 public final void setPriority(int newPriority) {    ThreadGroup g;    checkAccess();    // 主要看这句 如果大于MAX_PRIORITY  或者 小于MIN_PRIORITY 就抛异常     // 那最大是MAX_PRIORITY 喽  最小是MIN_PRIORITY 喽     if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {        throw new IllegalArgumentException();    }    if((g = getThreadGroup()) != null) {        if (newPriority > g.getMaxPriority()) {            newPriority = g.getMaxPriority();        }        setPriority0(priority = newPriority);    }} // 揭晓答案     /**     * 最小优先级     */    public final static int MIN_PRIORITY = 1;
/** * 默认优先级 */ public final static int NORM_PRIORITY = 5;
/** * 最大优先级 */ public final static int MAX_PRIORITY = 10;
复制代码


优先级有什么用呢? 上边说了


线程优先级高了获取 cpu 的概率高


但是不一定肯定比低优先级的线程先获取到 cpu 只是概率高


下边有一个例子测试优先级获取 cpu 的概率


public class ProTest02 {    public static void main(String[] args) throws InterruptedException {        ThreadGroup g = new ThreadGroup("测试分组");        // 4个线程  优先级:1 3 5 7        for (int i = 0; i < 4; i++) {            String str = String.valueOf("优先级为"+(2*i+1)+"的线程");            new TP(str,g,2*i+1).start();        }        Thread.sleep(3000);        g.interrupt();
}}
class TP extends Thread{ AtomicInteger a = new AtomicInteger(); public TP(String name,ThreadGroup tg,int pro){ super(tg,name); this.setPriority(pro);
} @Override public void run() { while (true){ try { Thread.sleep(1); a.incrementAndGet(); }catch (Exception e){ System.out.println(Thread.currentThread().getName()+"累加:"+a.get()); break; } } }}
// 输出结果 (不定)优先级为5的线程累加:2140优先级为7的线程累加:2294优先级为3的线程累加:431优先级为1的线程累加:139
复制代码


欢迎关注公众号:


用户头像

还未添加个人签名 2018.03.28 加入

还未添加个人简介

评论

发布
暂无评论
话说  用户线程&守护线程&线程组&线程优先级