關(guān)于Java多線程上下文切換的總結(jié)
什么是上下文切換
即使是單核CPU也支持多線程執(zhí)行代碼,CPU通過(guò)給每個(gè)線程分配CPU時(shí)間片來(lái)實(shí)現(xiàn)這個(gè)機(jī)制。時(shí)間片是CPU分配給各個(gè)線程的時(shí)間,因?yàn)闀r(shí)間片非常短,所以CPU通過(guò)不停地切換線程執(zhí)行,讓我們感覺(jué)多個(gè)線程時(shí)同時(shí)執(zhí)行的,時(shí)間片一般是幾十毫秒(ms)。
CPU通過(guò)時(shí)間片分配算法來(lái)循環(huán)執(zhí)行任務(wù),當(dāng)前任務(wù)執(zhí)行一個(gè)時(shí)間片后會(huì)切換到下一個(gè)任務(wù)。但是,在切換前會(huì)保存上一個(gè)任務(wù)的狀態(tài),以便下次切換回這個(gè)任務(wù)時(shí),可以再次加載這個(gè)任務(wù)的狀態(tài),從任務(wù)保存到再加載的過(guò)程就是一次上下文切換。
這就像我們同時(shí)讀兩本書(shū),當(dāng)我們?cè)谧x一本英文的技術(shù)書(shū)籍時(shí),發(fā)現(xiàn)某個(gè)單詞不認(rèn)識(shí),于是便打開(kāi)中英文詞典,但是在放下英文書(shū)籍之前,大腦必須先記住這本書(shū)讀到了多少頁(yè)的第多少行,等查完單詞之后,能夠繼續(xù)讀這本書(shū)。這樣的切換是會(huì)影響讀書(shū)效率的,同樣上下文切換也會(huì)影響多線程的執(zhí)行速度。
上下文切換代碼測(cè)試
下面的代碼演示串行和并發(fā)執(zhí)行并累加操作的時(shí)間:
public class ContextSwitchTest
{
private static final long count = 10000;
public static void main(String[] args) throws Exception
{
concurrency();
serial();
}
private static void concurrency() throws Exception
{
long start = System.currentTimeMillis();
Thread thread = new Thread(new Runnable(){
public void run()
{
int a = 0;
for (int i = 0; i < count; i++)
{
a += 5;
}
}
});
thread.start();
int b = 0;
for (long i = 0; i < count; i++)
{
b --;
}
thread.join();
long time = System.currentTimeMillis() - start;
System.out.println("Concurrency:" + time + "ms, b = " + b);
}
private static void serial()
{
long start = System.currentTimeMillis();
int a = 0;
for (long i = 0; i < count; i++)
{
a += 5;
}
int b = 0;
for (int i = 0; i < count; i++)
{
b --;
}
long time = System.currentTimeMillis() - start;
System.out.println("Serial:" + time + "ms, b = " + b + ", a = " + a);
}
}修改上面的count值,即修改循環(huán)次數(shù),看一下串行運(yùn)行和并發(fā)運(yùn)行的時(shí)間測(cè)試結(jié)果:

從表中可以看出,100次并發(fā)執(zhí)行累加以下,串行執(zhí)行和并發(fā)執(zhí)行的運(yùn)行速度總體而言差不多,1萬(wàn)次以下串行執(zhí)行甚至還可以說(shuō)是略快。為什么并發(fā)執(zhí)行的速度會(huì)比串行慢呢?這就是因?yàn)?strong>線程有創(chuàng)建和上下文切換的開(kāi)銷(xiāo)。
引起線程上下文切換的原因
對(duì)于我們經(jīng)常使用的搶占式操作系統(tǒng)而言,引起線程上下文切換的原因大概有以下幾種:
- 當(dāng)前執(zhí)行任務(wù)的時(shí)間片用完之后,系統(tǒng)CPU正常調(diào)度下一個(gè)任務(wù)
- 當(dāng)前執(zhí)行任務(wù)碰到IO阻塞,調(diào)度器將此任務(wù)掛起,繼續(xù)下一任務(wù)
- 多個(gè)任務(wù)搶占鎖資源,當(dāng)前任務(wù)沒(méi)有搶到鎖資源,被調(diào)度器掛起,繼續(xù)下一任務(wù)
- 用戶(hù)代碼掛起當(dāng)前任務(wù),讓出CPU時(shí)間
- 硬件中斷
如何減少上下文切換
既然上下文切換會(huì)導(dǎo)致額外的開(kāi)銷(xiāo),因此減少上下文切換次數(shù)便可以提高多線程程序的運(yùn)行效率。減少上下文切換的方法有無(wú)鎖并發(fā)編程、CAS算法、使用最少線程和使用協(xié)程。
- 無(wú)鎖并發(fā)編程。多線程競(jìng)爭(zhēng)時(shí),會(huì)引起上下文切換,所以多線程處理數(shù)據(jù)時(shí),可以用一些辦法來(lái)避免使用鎖,如將數(shù)據(jù)的ID按照Hash取模分段,不同的線程處理不同段的數(shù)據(jù)
- CAS算法。Java的Atomic包使用CAS算法來(lái)更新數(shù)據(jù),而不需要加鎖
- 使用最少線程。避免創(chuàng)建不需要的線程,比如任務(wù)很少,但是創(chuàng)建了很多線程來(lái)處理,這樣會(huì)造成大量線程都處于等待狀態(tài)
- 協(xié)程。在單線程里實(shí)現(xiàn)多任務(wù)的調(diào)度,并在單線程里維持多個(gè)任務(wù)間的切換
到此這篇關(guān)于關(guān)于Java多線程上下文切換的總結(jié)的文章就介紹到這了,更多相關(guān)Java多線程上下文切換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實(shí)現(xiàn)字符串和日期類(lèi)型相互轉(zhuǎn)換的方法
這篇文章主要介紹了java實(shí)現(xiàn)字符串和日期類(lèi)型相互轉(zhuǎn)換的方法,涉及java針對(duì)日期與字符串的轉(zhuǎn)換與運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-02-02
使用SpringBoot讀取Windows共享文件的代碼示例
在現(xiàn)代企業(yè)環(huán)境中,文件共享是一個(gè)常見(jiàn)的需求,Windows共享文件夾(SMB/CIFS協(xié)議)因其易用性和廣泛的兼容性,成為了許多企業(yè)的首選,在Java應(yīng)用中,尤其是使用Spring Boot框架時(shí),如何讀取Windows共享文件是一個(gè)值得探討的話題,本文介紹了使用SpringBoot讀取Windows共享文件2024-11-11
Java編程倒計(jì)時(shí)實(shí)現(xiàn)方法示例
這篇文章主要介紹了Java編程倒計(jì)時(shí)實(shí)現(xiàn)的三個(gè)示例,三種實(shí)現(xiàn)方法,具有一定參考價(jià)值,需要的朋友可以了解下。2017-09-09
knife4j3.0.3整合gateway和注冊(cè)中心的詳細(xì)過(guò)程
這篇文章主要介紹了knife4j3.0.3整合gateway和注冊(cè)中心的詳細(xì)過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
Spring Boot 通過(guò)注解實(shí)現(xiàn)數(shù)據(jù)校驗(yàn)的方法
這篇文章主要介紹了Spring Boot 通過(guò)注解實(shí)現(xiàn)數(shù)據(jù)校驗(yàn)的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
給Java文件打成獨(dú)立JAR包的詳細(xì)步驟記錄
這篇文章主要介紹了給Java文件打成獨(dú)立JAR包的相關(guān)資料,文中將Java文件打包成獨(dú)立的JAR包,包括非Maven和Maven項(xiàng)目的打包步驟,需要的朋友可以參考下2024-12-12
java token生成和校驗(yàn)的實(shí)例代碼
這篇文章主要介紹了java token生成和校驗(yàn)的實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09

