java并發(fā)編程(二):java并發(fā)基礎(chǔ)與基本應(yīng)用

一砌们、線程簡介

1杆麸、什么是線程

????現(xiàn)代操作系統(tǒng)在運行一個程序時,會為其創(chuàng)建一個進程浪感。例如啟動一個java程序昔头,就會創(chuàng)建一個java進程。線程是操作系統(tǒng)最小的調(diào)度單位影兽,也叫做輕量級進程减细,是進程中實際的運作單位。在一個進程里可以創(chuàng)建多個線程赢笨,每個線程的實體都包含程序計數(shù)器未蝌、堆棧、保留局部變量茧妒、寄存器萧吠、少數(shù)狀態(tài)參數(shù)等,這些線程都能訪問共享的內(nèi)存變量桐筏。

線程和進程的區(qū)別是:

????進程是操作系統(tǒng)資源分配的基本單位纸型,線程是任務(wù)調(diào)度和執(zhí)行的基本單位,進程不是一個可執(zhí)行實體,線程是能獨立運行的基本單位狰腌。

????進程間相互獨立除破,進程有單獨完整的虛擬地址空間,而線程間共享所屬進程的資源對其他進程不可見琼腔。

????進程間通信主要是管道瑰枫、消息隊列、信號丹莲、共享存儲光坝、套接字,而線程可以直接讀寫進程數(shù)據(jù)段(如全局變量)來通信甥材。

????線程的上下文切換比進程的上下文切換要快的多盯另,因為線程共享所屬進程的虛擬空間內(nèi)存,所以線程的上下文切換不必切換虛擬空間內(nèi)存洲赵,代價要小的多鸳惯。

????一個java程序從main()方法開始執(zhí)行,java實際上天生就是多線程程序叠萍,執(zhí)行main方法的是名叫main的線程芝发,大量的其他子線程都是從它這里產(chǎn)生的,mian線程不是守護線程俭令,通常它是最后一個執(zhí)行完畢的線程。下面用JMX來查看一個普通的Java程序包含哪些線程部宿。

《java并發(fā)編程的藝術(shù)》第4章第1節(jié)例子:


public static void main(String[] args) {

????ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

????ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);

????for (ThreadInfo threadInfo : threadInfos) {

????????System.out.println("[" + threadInfo.getThreadId() + "]" + threadInfo.getThreadName());

????}

}



書中給出的輸出內(nèi)容是:

????[4] Signal Dispatcher //分發(fā)處理發(fā)送給JVM信號的線程

????[3] Finalizer //調(diào)用對象 finalize 方法的線程

????[2] Reference Handler //清除Refernce的線程

????[1] main //main線程抄腔,用戶程序入口

據(jù)考證,在linux系統(tǒng)環(huán)境下會輸出書中一樣的結(jié)果


在windows下 jdk11會輸出:

????[1]main

????[2]Reference Handler

????[3]Finalizer

????[4]Signal Dispatcher

? ??[5]Attach Listener // jvm接收外部命令的線程理张,如果JVM啟動時每初始化赫蛇,那第一次執(zhí)行jvm命令時會啟動。

? ??[20]Common-Cleaner


在Mac系統(tǒng)下:

????[9] Monitor Ctrl-Break

????[4] Singal Dispatcher

????[3] Finalizer

????[2] Refernce Handler

????[1] main


2雾叭、為什么要使用多線程

????“執(zhí)行一個簡單的hello world程序悟耘,卻啟動了那么多無關(guān)線程,是不是把簡單的問題復(fù)雜化织狐?”暂幼,《java并發(fā)編程的藝術(shù)》書中回答說:當(dāng)然不是,因為正確使用多線程移迫,總是能夠給開發(fā)人員帶來顯著的好處....

????我認為如果只是執(zhí)行helloworld這種程序旺嬉,肯定不需要多線程環(huán)境執(zhí)行,但JVM的存在的意義不是執(zhí)行這么簡單的程序厨埋,而是根據(jù)需求得出最佳的編程模型邪媳,以較高的效率執(zhí)行代碼。所以,使用多線程的原因主要有以下幾點:

????1雨效、從執(zhí)行效率上講迅涮,在多核CPU系統(tǒng)上,將要執(zhí)行的任務(wù)分割成多個任務(wù)并行執(zhí)行徽龟,就可以顯著提高執(zhí)行效率叮姑。單核單線程處理器上,只能實現(xiàn)并發(fā)顿肺,也就是在一個時間區(qū)間內(nèi)戏溺,任務(wù)根據(jù)系統(tǒng)分配的時間片上下文切換先后執(zhí)行,因為時間片非常短屠尊,所以感覺是同時執(zhí)行的旷祸,但實際上不考慮阻塞會比單線程更慢。而并行執(zhí)行可以充分利用多核CPU的優(yōu)勢讼昆,多個任務(wù)同時跑在CPU上托享,無疑顯著的減少程序處理時間,提高代碼的執(zhí)行效率浸赫。

????2闰围、從程序設(shè)計角度上講,在一些適合的場合既峡,用多線程可以避免阻塞羡榴。比如在網(wǎng)絡(luò)編程上,IO操作會導(dǎo)致當(dāng)前線程阻塞运敢,但如果采用多線程校仑,可以避免因IO操作而導(dǎo)致無法接收其他客戶端的連接請求。在實際開發(fā)中传惠,比如查詢數(shù)據(jù)庫的操作迄沫,會導(dǎo)致當(dāng)前線程阻塞直到得到查詢結(jié)果,這對服務(wù)器程序來講無法接受卦方,所以可以在主線程外另起一個線程來做查詢操作羊瘩,將一些后續(xù)的操作放在這個線程里處理,可以充分避免因查詢阻塞而導(dǎo)致服務(wù)器卡頓的情況盼砍。????

二尘吗、線程的使用

1、線程優(yōu)先級

? ??線程優(yōu)先級在早期的java版本中可能很有用浇坐,但現(xiàn)在不推薦使用它摇予。在java線程中,可以通過一個整型成員變量priority來控制優(yōu)先級吗跋,范圍從1到10侧戴,在線程構(gòu)建時可通過setPriority來修改優(yōu)先級宁昭,默認優(yōu)先級是5。優(yōu)先級高的獲得時間片的幾率會大于優(yōu)先級低的酗宋。

????線程優(yōu)先級不能作為程序正確性的依賴积仗,因為操作系統(tǒng)可能完全不理會java線程對優(yōu)先級的設(shè)定。

2蜕猫、線程的狀態(tài)

????java線程在運行的生命周期中可能處于6種不同的狀態(tài)寂曹,在一個給定的時刻,線程只能處于其中的一個狀態(tài)回右。

????狀態(tài)名稱? ? ????????????說明

????NEW? ? ? ? ? ????????????初始狀態(tài)隆圆,線程被構(gòu)建,但還沒調(diào)用start方法

????RUNNABLE? ? ? ? ? ?運行狀態(tài)翔烁,Java線程將操作系統(tǒng)中的就緒和運行兩種狀態(tài)籠統(tǒng)地稱作“運行中”

????BLOCKED? ? ? ? ? ? ?阻塞狀態(tài)渺氧,表示線程阻塞于鎖

????WAITING? ? ? ? ? ? ? ?等待狀態(tài),表示線程進入等待狀態(tài)蹬屹,進入該狀態(tài)表示當(dāng)前線程需要等待其他線程做出一些特定動作(通知或中斷)

????TIME_WAITING? ? 超時等待狀態(tài)侣背,該狀態(tài)不同于WAITING,它是可以在指定的時間自行返回的

????TERMINATED? ? ? ?終止狀態(tài)慨默,表示當(dāng)前線程已經(jīng)執(zhí)行完畢


3贩耐、Daemon守護線程

????Daemon線程是一種支持型線程,因為它主要被用作程序中后臺調(diào)度以及支持性工作厦取。這意味著潮太,當(dāng)一個java虛擬機中不存在非Daemon線程的時候骨杂,Java虛擬機將會退出涩馆。可以調(diào)用Thread.setDaemon(true)將線程設(shè)置為Daemon線程低淡,但要在線程執(zhí)行start方法之前初始狀態(tài)設(shè)置台谢,不能在啟動線程之后設(shè)置寻狂。

????Daemon線程被用作完成支持性工作岁经,但是在java虛擬機退出時Daemon線程中的finally塊并不一定會執(zhí)行朋沮,所以在構(gòu)建Daemon線程時,不能依靠finally塊中的內(nèi)容來確保執(zhí)行關(guān)閉或清理資源的邏輯缀壤。

4樊拓、線程的啟動和終止

4.1 構(gòu)造線程:

????在運行線程之前首先要構(gòu)造一個線程對象,線程對象在構(gòu)造的時候需要提供線程所需要的屬性塘慕,如線程所屬的線程組筋夏、線程優(yōu)先級、是否是Daemon線程等信息图呢。

java源碼 jdk11.0.3

????在構(gòu)建過程中条篷,一個新構(gòu)造的線程對象是由其parent線程來進行空間分配的骗随,而child線程繼承了parent是否為Daemon、優(yōu)先級和加載資源的contextClassLoader以及可繼承的ThreadLocal赴叹,同時還會分配一個唯一ID來標識這個child線程鸿染。至此,一個能夠運行得線程對象就初始化好了乞巧,在堆內(nèi)存中等待著運行涨椒。

? ??創(chuàng)建線程的四種方式:繼承Thread類、實現(xiàn)runnable接口绽媒、實現(xiàn)callable接口蚕冬、使用線程池創(chuàng)建

4.2 啟動線程:

????線程對象初始化完成后,調(diào)用start()方法就可以啟動這個線程是辕。線程start()方法的含義是:當(dāng)前線程(即parent線程)同步告知Java虛擬機囤热,只要線程規(guī)劃器空閑,應(yīng)立即啟動調(diào)用start()方法的線程免糕,調(diào)用該線程的run()方法赢乓。

4.3 理解中斷:

????在程序中免不得要碰到需要暫停或停止當(dāng)前線程的情況石窑,比如負責(zé)下載的程序會占用大部分帶寬牌芋,用戶想玩網(wǎng)游就要暫停下載任務(wù),這個時候就要停止當(dāng)前的線程讓出帶寬給用戶玩游戲松逊,而這種情況就需要用到線程的中斷機制躺屁。

????中斷可以理解為線程的一個標識位屬性,它表示一個運行中的線程是否被其他線程進行了中斷操作经宏。中斷好比其他線程對該線程打了個招呼犀暑,其他線程調(diào)用該線程的interrupt()方法對其進行中斷操作。

????線程通過方法isInterrupted()來進行判斷是否被中斷烁兰,也可以調(diào)用靜態(tài)方法Thread.interrupted()對當(dāng)前線程的中斷標識位進行復(fù)位耐亏。如果該線程已經(jīng)處于終結(jié)狀態(tài),即使該線程被中斷過沪斟,在調(diào)用該線程對象的isInterrupted()時依舊會返回false广辰。

????從Java的API中可以看到,許多聲明拋出InterruptedException的方法(例如Thread.sleep(long millis)方法)這些方法在拋出InterruptedException之前主之,Java虛擬機會先將該線程的中斷標識位清除择吊,然后拋出InterruptedException,此時調(diào)用isInterrupted()方法將會返回false槽奕。

????可以看一下以下例子觀察兩個線程的中斷標識位几睛。


????輸出的結(jié)果:


????從結(jié)果可以看出,拋出InterruptedException的線程SleepThread粤攒,其中斷標識位被清除了所森,而一直忙碌運作的線程BusyThread囱持,中斷標識位沒有被清除。

4.4 過期的suspend()焕济、resume()和stop()

????大家對于CD機肯定不會陌生洪唐,如果把它播放音樂比作一個線程的運作,那么對音樂播放做出的暫停吼蚁、恢復(fù)和停止操作對應(yīng)在線程Thread的API就是suspend()凭需、resume()和stop()。

????在以下代碼中肝匆,創(chuàng)建了一個線程PrintThread粒蜈,它以1秒的頻率進行打印,而主線程對其進行暫停旗国、恢復(fù)和停止操作枯怖。


????輸出如下:(輸出內(nèi)容中的時間與示例執(zhí)行的具體時間相關(guān))

????在執(zhí)行過程中,PrintThread運行了3秒能曾,隨后被暫停度硝,3秒后恢復(fù),最后經(jīng)過3秒被終止寿冕。通過示例的輸出可以看到蕊程,suspend()、resume()和stop()方法完成了線程的暫停驼唱、恢復(fù)和終止藻茂,而且非常“人性化”玫恳。但是這些API是過期的辨赐,不建議使用。

????不建議使用的主要原因有:suspend()方法在調(diào)用后京办,線程不會釋放已經(jīng)占有的資源(比如鎖)掀序,而是占有著資源進入睡眠狀態(tài),這樣容易引發(fā)死鎖問題惭婿。同樣不恭,stop()方法在終結(jié)一個線程時不會保證線程的資源正常釋放,通常是沒有給線程完成資源釋放工作的機會审孽,因此會導(dǎo)致程序可能工作在不確定狀態(tài)下县袱。

????暫停和恢復(fù)操作可以用等待/通知機制替代浑娜。

4.5 安全地終止線程

????可以采用對線程設(shè)置中斷標識后安全的終止線程佑力。使用interrupt()方法設(shè)置線程的中斷標識位,由該線程檢測進行中斷筋遭。另外還可以在該線程中自主增加一個boolean類型用于判斷是否終止該線程打颤。


????輸出結(jié)果:(輸出內(nèi)容可能不同)


三暴拄、常見面試題問題

????1、線程和進程的區(qū)別是什么

????2编饺、線程的狀態(tài)有哪幾種

????3乖篷、Java中創(chuàng)建線程有幾種方式,你喜歡哪一種透且,為什么

????4撕蔼、如何安全的終止線程

????5、為什么不推薦使用suspend()秽誊、resume()和stop()

????摘抄出處:《java并發(fā)編程的藝術(shù)》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鲸沮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子锅论,更是在濱河造成了極大的恐慌讼溺,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件最易,死亡現(xiàn)場離奇詭異怒坯,居然都是意外死亡,警方通過查閱死者的電腦和手機藻懒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門剔猿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嬉荆,你說我怎么就攤上這事艳馒。” “怎么了员寇?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵弄慰,是天一觀的道長。 經(jīng)常有香客問我蝶锋,道長陆爽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任扳缕,我火速辦了婚禮慌闭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘躯舔。我一直安慰自己驴剔,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布粥庄。 她就那樣靜靜地躺著丧失,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惜互。 梳的紋絲不亂的頭發(fā)上布讹,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天琳拭,我揣著相機與錄音,去河邊找鬼描验。 笑死白嘁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的膘流。 我是一名探鬼主播絮缅,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼呼股!你這毒婦竟也來了盟蚣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤卖怜,失蹤者是張志新(化名)和其女友劉穎屎开,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體马靠,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡奄抽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了甩鳄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逞度。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖妙啃,靈堂內(nèi)的尸體忽然破棺而出档泽,到底是詐尸還是另有隱情,我是刑警寧澤揖赴,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布馆匿,位于F島的核電站,受9級特大地震影響燥滑,放射性物質(zhì)發(fā)生泄漏渐北。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一铭拧、第九天 我趴在偏房一處隱蔽的房頂上張望赃蛛。 院中可真熱鬧,春花似錦搀菩、人聲如沸呕臂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽歧蒋。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間疏尿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工易桃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留褥琐,地道東北人。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓晤郑,卻偏偏與公主長得像敌呈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子造寝,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容