日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
面試官:有了解過線程組和線程優(yōu)先級(jí)嗎?

什么是線程組

public class ThreadGroupTest {
public static void main(String[] args) {
new Thread(() -> {
System.out.println(Thread.currentThread().getThreadGroup().getName());
}).start();
System.out.println(Thread.currentThread().getThreadGroup().getName());
}
}

輸出:

main
main

可以發(fā)現(xiàn)在main線程組下;

ThreadGroup是一個(gè)標(biāo)準(zhǔn)的「向下引用」的樹狀結(jié)構(gòu),這樣設(shè)計(jì)的原因是「防止"上級(jí)"線程被"下級(jí)"線程引用而無法有效地被GC回收」。

線程優(yōu)先級(jí)

線程的優(yōu)先級(jí)級(jí)別由操作系統(tǒng)決定,不同的操作系統(tǒng)級(jí)別是不一樣的,在Java中,提供了一個(gè)級(jí)別范圍1~10,方便我們?nèi)⒖?。Java默認(rèn)的線程優(yōu)先級(jí)為5,線程的執(zhí)行順序由調(diào)度程序來決定,線程的優(yōu)先級(jí)會(huì)在線程被調(diào)用之前設(shè)定。

源碼描述:

/**
* 最低級(jí)別
*/
public final static int MIN_PRIORITY = 1;

/**
* 默認(rèn)級(jí)別
*/
public final static int NORM_PRIORITY = 5;

/**
* 最高級(jí)別
*/
public final static int MAX_PRIORITY = 10;

獲取線程優(yōu)先級(jí)別

public static void main(String[] args) {
new Thread(() -> {
System.out.println("default level: {}" + Thread.currentThread().getPriority());
}).start();
}

輸出: default level: {}5

設(shè)置級(jí)別

public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("default level: {}" + Thread.currentThread().getPriority());
});
t.start();
t.setPriority(10);
}

輸出: default level: {}10

通常來講,高級(jí)別的優(yōu)先級(jí)往往會(huì)更高幾率的執(zhí)行,注意這里是概率性問題,下面我們測(cè)試一下:

public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("hello " + Thread.currentThread().getPriority());
System.out.println("default level: {}" + Thread.currentThread().getPriority());
});
t.setPriority(3);

Thread t1 = new Thread(() -> {
System.out.println("hello " + Thread.currentThread().getPriority());
System.out.println("default level: {}" + Thread.currentThread().getPriority());
});
t1.setPriority(7);

Thread t2 = new Thread(() -> {
System.out.println("hello " + Thread.currentThread().getPriority());
System.out.println("default level: {}" + Thread.currentThread().getPriority());
});
t2.setPriority(10);


t.start();
t1.start();
t2.start();
}

第一次輸出:

hello 7
default level: {}7
hello 10
default level: {}10
hello 3
default level: {}3

第二次:

hello 3
default level: {}3
hello 7
default level: {}7
hello 10
default level: {}10

第三次

hello 10
default level: {}10
hello 7
default level: {}7
hello 3
default level: {}3

...

發(fā)現(xiàn),不斷的嘗試之后,高級(jí)別出現(xiàn)的概率會(huì)比較靠前一點(diǎn), 所以想要借助它來完成一些特定業(yè)務(wù)的同學(xué)注意了,不建議使用,不靠譜,之前也講到,底層還是由操作系統(tǒng)調(diào)度完成

Java提供一個(gè)「線程調(diào)度器」來監(jiān)視和控制處于「RUNNABLE狀態(tài)」的線程。線程的調(diào)度策略采用「搶占式」,優(yōu)先級(jí)高的線程比優(yōu)先級(jí)低的線程會(huì)有更大的幾率優(yōu)先執(zhí)行。在優(yōu)先級(jí)相同的情況下,按照“先到先得”的原則。每個(gè)Java程序都有一個(gè)默認(rèn)的主線程,就是通過JVM啟動(dòng)的第一個(gè)線程main線程。

除了主線程之外,還有一個(gè)線程是守護(hù)線程,它的優(yōu)先級(jí)比較低。如果所有的非守護(hù)線程都結(jié)束了,這個(gè)守護(hù)線程也會(huì)自動(dòng)結(jié)束??梢越柚鼘?shí)現(xiàn)一些特定場(chǎng)景,比如手動(dòng)關(guān)閉線程的場(chǎng)景,某些場(chǎng)景下不關(guān)閉,會(huì)造成資源浪費(fèi),手動(dòng)關(guān)閉又很麻煩。這里我們可以通過setDaemon(true)指定。

public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("hello " + Thread.currentThread().getPriority());
System.out.println("default level: {}" + Thread.currentThread().getPriority());
});
t.setDaemon(true); // 默認(rèn)為false
t.setPriority(10);

Thread t1 = new Thread(() -> {
System.out.println("hello " + Thread.currentThread().getPriority());
System.out.println("default level: {}" + Thread.currentThread().getPriority());
});
t1.setPriority(7);

t.start();
t1.start();
}

輸出:

hello 7
default level: {}7
hello 10
default level: {}10

發(fā)現(xiàn)即使指定了高級(jí)別,執(zhí)行的優(yōu)先級(jí)仍然是最低的

線程組下的優(yōu)先級(jí)

剛剛我們都是在main線程組下,舉一反三,線程組下的優(yōu)先級(jí)又是怎么樣的呢下面,測(cè)試一下:

public static void main(String[] args) {
// 指定 name 為 g1的線程組
ThreadGroup group = new ThreadGroup("g1");
group.setMaxPriority(4);

Thread t = new Thread(group, () -> {
System.out.println("hello " + Thread.currentThread().getPriority());
System.out.println("default level: {}" + Thread.currentThread().getPriority());
}, "t0");
t.setPriority(10);
t.start();
}

輸出:

hello 4
default level: {}4

發(fā)現(xiàn),在g1線程組下指定了最大優(yōu)先級(jí)后,線程t0的優(yōu)先級(jí)最大級(jí)別只能是4, 所以這也是使用線程組的好處。

我們可以通過如下方式復(fù)制線程組, ThreadGroup提供了enumerate方法:

public static void main(String[] args) throws InterruptedException {
// 指定 name 為 g1的線程組
ThreadGroup group = new ThreadGroup("g1");
group.setMaxPriority(4);

Thread t = new Thread(group, () -> {
System.out.println("hello " + Thread.currentThread().getPriority());
System.out.println("default level: {}" + Thread.currentThread().getPriority());
}, "t0");
t.setPriority(10);
t.start();

// 復(fù)制線程組
System.out.println(group.activeCount()); // 1
Thread[] list = new Thread[group.activeCount()];
group.enumerate(list);

Thread.sleep(3000);
System.out.println(list[0].getName()); // 輸出 t0

}

統(tǒng)一異常捕獲

public static void main(String[] args) {
// 指定 name 為 g1的線程組
ThreadGroup group = new ThreadGroup("g1") {
// 統(tǒng)一異常捕獲
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t.getName() + ": " + e.getMessage()); // t0: 我出錯(cuò)了
}
};
group.setMaxPriority(4);

Thread t = new Thread(group, () -> {
System.out.println("hello " + Thread.currentThread().getPriority());
System.out.println("default level: {}" + Thread.currentThread().getPriority());
throw new RuntimeException("我出錯(cuò)了");
}, "t0");
t.setPriority(10);
t.start();
}

向下引用的樹狀數(shù)據(jù)結(jié)構(gòu)

線程組的內(nèi)部其實(shí)不單單可以放線程,其實(shí)也可以放其它線程組,我們看下源碼定義

 public static void main(String[] args) {
// 指定 name 為 g1的線程組
ThreadGroup group = new ThreadGroup("g1") {
// 統(tǒng)一異常捕獲
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t.getName() + ": " + e.getMessage()); // t0: 我出錯(cuò)了
}
};
group.setMaxPriority(4);

Thread t = new Thread(group, () -> {
System.out.println("hello " + Thread.currentThread().getPriority());
System.out.println("default level: {}" + Thread.currentThread().getPriority());
throw new RuntimeException("我出錯(cuò)了");
}, "t0");
t.setPriority(10);
t.start();
}

這里大家可以大膽去猜測(cè)一下,為什么要采用這種數(shù)據(jù)結(jié)構(gòu)其實(shí)你通過源碼發(fā)現(xiàn),它的內(nèi)部很多地方都調(diào)用了checkAccess方法,特別是在set操作,字面意思是檢查是否有權(quán)限,我看下這個(gè)方法。

public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}

它調(diào)用了一個(gè)SecurityManager, 它是Java的安全管理器,它允許應(yīng)用程序在執(zhí)行一個(gè)可能不安全或敏感的操作前確定該操作是什么,以及是否是在允許執(zhí)行該操作的安全上下文中執(zhí)行它。應(yīng)用程序可以允許或不允許該操作??偟膩碚f就是保證安全性。

通過上面的了解,我們應(yīng)該知道為什么要用這種樹狀結(jié)構(gòu)了。它都是一層一層級(jí)別的控制,這么做方便去管理,提高安全性,出了問題也能很快的定位到。就像公司的人員組織架構(gòu)一樣,一切都是為了管理好公司。

結(jié)束語

本篇內(nèi)容到這里就結(jié)束了, 大家自己一定要多去理解,不要去背,。


分享文章:面試官:有了解過線程組和線程優(yōu)先級(jí)嗎?
URL鏈接:http://m.5511xx.com/article/djcgdsp.html