話說 用戶線程&守護線程&線程組&線程優先級

用戶線程&守護線程&線程組&線程優先級

若是把公司比喻成進程,java

那麼你和我就是用戶線程,程序員

後勤部門就是守護線程(負責給你訂水,打掃辦公環境等),ide

每一個項目組就是一個線程組,函數

程序員等級就是優先級(高級程序員 總比初級程序員容易獲取資源 機率大 但不是確定)。測試

1、 用戶線程&守護線程
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次可是也就結束了this

公司都沒有研發、銷售、市場等職位了,後勤也就沒有必要留着了。spa

那new Thread() 默認是守護線程仍是用戶線程 ? 線程

答案: 不肯定,要看父線程 新new的線程 默認與父線程一致code

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);
}
// 下邊說的線程組ThreadGroup
private 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();
    
    // 一堆代碼...
}
2、 線程組

在上邊代碼中咱們看到,線程的默認分組是經過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();
        // 還有一些其餘的 讀者闊以本身去看看 瞭解爲主
    }
3、 優先級

在」一「中咱們看源碼的時候看到了,優先級默認是獲取的父線程的優先級 ,

那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

有問題能夠留言哦,或公衆號留言(回覆快):
image

相關文章
相關標籤/搜索