Java多線程實(shí)現(xiàn)之線程調(diào)度的使用
Java多線程中線程調(diào)度是一個(gè)核心概念,它決定了線程如何獲得CPU資源并執(zhí)行。合理的線程調(diào)度策略能夠充分發(fā)揮多核處理器的性能,提高程序的執(zhí)行效率。本文我將深入探討Java線程調(diào)度的原理、機(jī)制以及相關(guān)的API,帶你更好地理解和控制線程的執(zhí)行。
一、線程調(diào)度基礎(chǔ)概念
1.1 線程調(diào)度器
線程調(diào)度器是JVM的一部分,負(fù)責(zé)決定哪個(gè)線程獲得CPU時(shí)間片以及執(zhí)行多長(zhǎng)時(shí)間。Java線程調(diào)度器采用搶占式調(diào)度模型,即高優(yōu)先級(jí)的線程可以搶占低優(yōu)先級(jí)線程的CPU資源。
1.2 時(shí)間片
時(shí)間片是線程在CPU上執(zhí)行的最小時(shí)間單位。調(diào)度器會(huì)為每個(gè)線程分配一個(gè)時(shí)間片,當(dāng)時(shí)間片用完后,該線程會(huì)被暫停執(zhí)行,調(diào)度器會(huì)選擇另一個(gè)線程執(zhí)行。
1.3 線程狀態(tài)轉(zhuǎn)換
線程在其生命周期中會(huì)經(jīng)歷多種狀態(tài),調(diào)度器在這些狀態(tài)之間進(jìn)行轉(zhuǎn)換:
- 新建(New):線程被創(chuàng)建但尚未啟動(dòng)
- 就緒(Runnable):線程正在等待CPU資源
- 運(yùn)行(Running):線程正在CPU上執(zhí)行
- 阻塞(Blocked):線程因等待鎖、IO等原因暫停執(zhí)行
- 等待(Waiting):線程等待其他線程通知
- 超時(shí)等待(Timed Waiting):線程在指定時(shí)間內(nèi)等待
- 終止(Terminated):線程執(zhí)行完畢或異常終止
二、線程優(yōu)先級(jí)
2.1 優(yōu)先級(jí)范圍
Java線程優(yōu)先級(jí)范圍從1到10,數(shù)值越大優(yōu)先級(jí)越高:
Thread.MIN_PRIORITY= 1Thread.NORM_PRIORITY= 5(默認(rèn)優(yōu)先級(jí))Thread.MAX_PRIORITY= 10
2.2 設(shè)置線程優(yōu)先級(jí)
通過(guò)setPriority(int priority)方法設(shè)置線程優(yōu)先級(jí):
Thread highPriorityThread = new Thread(() -> {
// 高優(yōu)先級(jí)線程任務(wù)
});
highPriorityThread.setPriority(Thread.MAX_PRIORITY);
Thread lowPriorityThread = new Thread(() -> {
// 低優(yōu)先級(jí)線程任務(wù)
});
lowPriorityThread.setPriority(Thread.MIN_PRIORITY);
2.3 優(yōu)先級(jí)注意事項(xiàng)
- 優(yōu)先級(jí)不保證執(zhí)行順序:高優(yōu)先級(jí)線程只是更有可能獲得CPU資源,但不保證一定先執(zhí)行
- 平臺(tái)依賴性:不同操作系統(tǒng)對(duì)線程優(yōu)先級(jí)的支持不同,可能導(dǎo)致優(yōu)先級(jí)行為不一致
- 避免過(guò)度依賴優(yōu)先級(jí):應(yīng)通過(guò)合理的同步機(jī)制而非優(yōu)先級(jí)來(lái)控制線程執(zhí)行順序
三、線程調(diào)度方法
3.1 Thread.sleep(long millis)
使當(dāng)前線程暫停執(zhí)行指定的毫秒數(shù),線程進(jìn)入超時(shí)等待狀態(tài):
try {
Thread.sleep(1000); // 暫停1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
3.2 Thread.yield()
提示調(diào)度器當(dāng)前線程愿意讓出CPU資源,線程進(jìn)入就緒狀態(tài):
public void run() {
for (int i = 0; i < 100; i++) {
// 執(zhí)行一些工作
if (i % 10 == 0) {
Thread.yield(); // 讓出CPU資源
}
}
}
3.3 Thread.join()
等待指定線程執(zhí)行完畢:
Thread t = new Thread(() -> {
// 執(zhí)行耗時(shí)操作
});
t.start();
try {
t.join(); // 等待線程t執(zhí)行完畢
} catch (InterruptedException e) {
e.printStackTrace();
}
3.4 Object.wait() / notify() / notifyAll()
用于線程間通信,實(shí)現(xiàn)線程的協(xié)作:
class SharedResource {
private boolean ready = false;
public synchronized void waitForReady() throws InterruptedException {
while (!ready) {
wait(); // 線程等待
}
}
public synchronized void setReady() {
ready = true;
notifyAll(); // 喚醒所有等待的線程
}
}
四、線程調(diào)度策略
4.1 搶占式調(diào)度
Java默認(rèn)采用搶占式調(diào)度,高優(yōu)先級(jí)線程可以搶占低優(yōu)先級(jí)線程的CPU資源。但這種搶占不是絕對(duì)的,具體還取決于操作系統(tǒng)的調(diào)度策略。
4.2 公平鎖與非公平鎖
- 公平鎖:線程按照請(qǐng)求鎖的順序獲得鎖,保證公平性但可能降低吞吐量
- 非公平鎖:允許線程在鎖釋放時(shí)直接競(jìng)爭(zhēng),可能導(dǎo)致某些線程長(zhǎng)期得不到鎖
4.3 守護(hù)線程
守護(hù)線程是為其他線程提供服務(wù)的線程,當(dāng)所有非守護(hù)線程結(jié)束時(shí),JVM會(huì)自動(dòng)終止守護(hù)線程:
Thread daemonThread = new Thread(() -> {
// 守護(hù)線程任務(wù)
});
daemonThread.setDaemon(true); // 設(shè)置為守護(hù)線程
daemonThread.start();
五、線程池中的調(diào)度
5.1 線程池的調(diào)度策略
線程池通過(guò)ExecutorService接口提供,常見(jiàn)的線程池實(shí)現(xiàn)有:
FixedThreadPool:固定大小的線程池CachedThreadPool:可緩存的線程池ScheduledThreadPool:支持定時(shí)任務(wù)的線程池
5.2 自定義線程池調(diào)度
通過(guò)ThreadPoolExecutor可以自定義線程池的調(diào)度策略:
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // 核心線程數(shù)
10, // 最大線程數(shù)
60, // 空閑線程存活時(shí)間
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100), // 任務(wù)隊(duì)列
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略
);
六、線程調(diào)度的最佳實(shí)踐
6.1 避免過(guò)度依賴優(yōu)先級(jí)
線程優(yōu)先級(jí)應(yīng)謹(jǐn)慎使用,過(guò)度依賴優(yōu)先級(jí)可能導(dǎo)致程序行為不穩(wěn)定,尤其是在不同操作系統(tǒng)上。
6.2 合理使用sleep和yield
sleep()用于精確控制線程暫停時(shí)間yield()用于提示調(diào)度器讓出CPU資源,但不保證一定會(huì)讓出
6.3 優(yōu)先使用線程池
線程池提供了更高級(jí)的調(diào)度控制和資源管理,應(yīng)優(yōu)先使用線程池而非手動(dòng)創(chuàng)建線程。
6.4 正確處理線程中斷
在線程中正確處理InterruptedException,確保線程可以被優(yōu)雅地終止:
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// 線程任務(wù)
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢復(fù)中斷狀態(tài)
break;
}
}
}
總結(jié)
Java線程調(diào)度是一個(gè)復(fù)雜的機(jī)制,涉及優(yōu)先級(jí)、狀態(tài)轉(zhuǎn)換、同步等多個(gè)方面,理解線程調(diào)度的原理和機(jī)制,能夠幫助我們更好地控制線程執(zhí)行,提高程序性能和穩(wěn)定性,實(shí)際開(kāi)發(fā)中我們應(yīng)遵循最佳實(shí)踐,合理使用線程調(diào)度相關(guān)的API,通過(guò)線程池、同步機(jī)制等工具,構(gòu)建出高效、健壯的多線程應(yīng)用程序。
到此這篇關(guān)于Java多線程實(shí)現(xiàn)之線程調(diào)度的使用的文章就介紹到這了,更多相關(guān)Java多線程實(shí)現(xiàn)線程調(diào)度內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java GUI編程之布局控制器(Layout)實(shí)例分析
這篇文章主要介紹了java GUI編程之布局控制器(Layout),結(jié)合實(shí)例形式分析了java GUI編程中布局控制器(Layout)具體功能、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2020-01-01
SpringBoot深入刨析數(shù)據(jù)層技術(shù)
這篇文章主要介紹了SpringBoot數(shù)據(jù)層技術(shù)的解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
SpringSecurity+jwt+redis基于數(shù)據(jù)庫(kù)登錄認(rèn)證的實(shí)現(xiàn)
本文主要介紹了SpringSecurity+jwt+redis基于數(shù)據(jù)庫(kù)登錄認(rèn)證的實(shí)現(xiàn),其中也涉及到自定義的過(guò)濾器和處理器,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09
使用.NET Core3.0創(chuàng)建一個(gè)Windows服務(wù)的方法
這篇文章主要介紹了使用.NET Core3.0創(chuàng)建一個(gè)Windows服務(wù)的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-04-04
Maven打包所有依賴到一個(gè)可執(zhí)行jar中遇到的問(wèn)題
這篇文章主要給大家介紹了關(guān)于Maven打包所有依賴到一個(gè)可執(zhí)行jar中遇到的問(wèn)題,將依賴打入jar包,由于maven管理了所有的依賴,所以將項(xiàng)目的代碼和依賴打成一個(gè)包對(duì)它來(lái)說(shuō)是順理成章的功能,需要的朋友可以參考下2023-10-10
Java基于字符流形式讀寫數(shù)據(jù)的兩種實(shí)現(xiàn)方法示例
這篇文章主要介紹了Java基于字符流形式讀寫數(shù)據(jù)的兩種實(shí)現(xiàn)方法示,結(jié)合實(shí)例形式分析了java逐個(gè)字符讀寫及使用緩沖區(qū)進(jìn)行讀寫操作的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下2018-01-01

