Java基礎day11筆記:多線程概述|創(chuàng)建線程的兩個方法|線程的運行狀態(tài)|Thread中的一些方法|多線程的安全問題|多線程同步代碼塊

????01-多線程(概述)

? ? ? ? 接下來惭嚣,我們來說一說Java中特有的一個知識技術:多線程瞳脓。

? ? ? ? 在說線程這個概念之前呢,需要說一個更顯而易見的概念:進程。

? ? ? ? 何為進程呢形庭?進程就是正在進行中的程序铅辞。

? ? ? ? 進程可以同時開啟,其實就是cpu在對它們執(zhí)行萨醒。

? ? ? ? 不過斟珊,雖然它們看起來像是同時在執(zhí)行,其實验靡,cpu在某一時刻只能執(zhí)行某一個程序倍宾,它只是在做著超快的切換,咻咻咻咻~才導致我們看到的是各個程序在同時執(zhí)行胜嗓。

? ? ? ? 再講個迅雷的例子。是不是有時候會有多條下載請求呀钩乍?一個進程辞州,里面可能會有多條執(zhí)行路徑。什么意思呢寥粹?在我們進行迅雷下載的時候呢变过,大家都知道迅雷可以有多條下載路徑,比如100M的文件涝涤,迅雷可能會分成五個部分媚狰,一個部分一個部分的同時發(fā)送請求到服務端去下載數(shù)據(jù)。我們想一想阔拳,如果我們下載是用一個路徑崭孤,就是先下載第一個數(shù)據(jù),然后一個一個下載糊肠,一直下載到第100個數(shù)據(jù)辨宠。可是如果是五條路徑下載货裹,五個人同時在搬東西嗤形,是不是就比一個人快多啦?而且這五個人都是在這一個進程中哦弧圆,這其中的每一個人赋兵,就叫做線程。線程是進程中的內(nèi)容搔预,每一個應用程序霹期,里面都至少有一個線程。

? ? ? ? 線程有一個特點斯撮,它是程序中的控制單元经伙,或者叫執(zhí)行路徑。

? ? ? ? 總結(jié)一下:

? ? ? ? 進程:是一個正在執(zhí)行中的程序。

? ? ? ? ? ? ? ? ?每一個進程執(zhí)行都有一個執(zhí)行順序帕膜,該順序是一個執(zhí)行路徑枣氧,或者叫一個控制單元。

? ? ? ? 每個程序執(zhí)行垮刹,都需要啟動內(nèi)存空間达吞,而進程其實就是用來標識內(nèi)存空間的,它用來封裝里面的那些控制單元荒典。

? ? ? ? 線程:就是進程中的一個獨立的控制單元酪劫。

? ? ? ? ? ? ? ? ? 線程在控制著進程的執(zhí)行。

? ? ? ? ? ? ? ? ? 一個進程中至少有一個線程寺董。

? ? ? ? 以Java為例覆糟,編譯運行的時候,它有兩個進程:編譯進程和運行進程遮咖。

? ? ? ? 我們重點說一下運行進程滩字。

? ? ? ? Java虛擬機啟動的時候會有一個進程java.exe。該進程中至少有一個線程來負責Java程序的執(zhí)行御吞,而且這個線程運行的代碼存在于main方法中麦箍。該線程稱之為主線程。

? ? ? ? 其實陶珠,很多書里面都在說挟裂,這個程序在啟動執(zhí)行的時候是單線程程序,因為還沒有其他線程存在呢揍诽。這樣說理解也是對的诀蓉。

? ? ? ? 擴展:

? ? ? ? 但是,如果你深究一下虛擬機的話寝姿,其實不是單線程交排。虛擬機啟動的時候,它就是多線程饵筑。為什么呢埃篓?另外的線程是誰呢?

? ? ? ? 試想一下根资,(這個只作為了解喔架专,因為說這個程序是單線程也沒問題噠)程序在運行的時候,是不是要建立對象玄帕,調(diào)用方法部脚,這個時候是主線程在幫我們做這件事情,堆里面會產(chǎn)生很多對象裤纹,如果其中某一個對象不被使用了委刘,它就會被垃圾回收機制回收了丧没。主線程還在繼續(xù)執(zhí)行著其他對象中的操作,而這個對象就被干掉了锡移,是不是在同時進行吶呕童?是滴!

? ? ? ? 這個時候就產(chǎn)生了一個問題淆珊,主線程在繼續(xù)調(diào)用方法的同時夺饲,另外的不被使用的對象就被垃圾回收機制回收了。所以這個時候虛擬機至少有兩個線程施符,一個是主線程往声,一個是垃圾回收的線程。

? ? ? ? 多線程存在的意義是什么呢戳吝?

? ? ? ? 多線程的出現(xiàn)呢浩销,可以讓我們程序中的部分產(chǎn)生同時運行的效果。而且在下載東西的時候骨坑,多線程下載還可以幫我們提高效率撼嗓。

????02-多線程(創(chuàng)建線程-繼承Thread類)

? ? ? ? 那么,如何在我們的程序中自定一個控制單元欢唾,或者說,自定一個線程粉捻?

? ? ? ? Java中已經(jīng)為我們提供好了對這類事物的對象體現(xiàn)礁遣。

? ? ? ? 通過對API的查找,我們發(fā)現(xiàn)肩刃,java的核心包java.lang包中就有一個對象叫做Thread祟霍,它就是程序中的執(zhí)行線程,就是用于描述控制單元這類事物的對象盈包。

? ? ? ? 我們發(fā)現(xiàn)創(chuàng)建新執(zhí)行線程有兩種方法:

? ? ? ? 連范例都有啦沸呐,我們自己來寫~

? ? ? ? 創(chuàng)建線程的第一種方式:繼承Thread類。? ? ? ?

? ? ? ? 第一步蒙具,繼承Thread類:

? ? ? ? 接下來我們看看Thread中的run方法是怎樣的~

? ? ? ? 第二部俐填,重寫run方法:

? ? ? ? 繼承完之后揣非,我們接下來就要創(chuàng)建它的對象啦。注意哦呼渣,建立好一個對象,其實就是創(chuàng)建好一個線程寞埠。

? ? ? ? 創(chuàng)建好對象之后就要調(diào)用run方法啦屁置。

? ? ? ? 我們看到范例中有一個start方法:

? ? ? ? 查一下start方法是干什么的~

? ? ? ? OK,寫好啦:
? ??????

? ? ? ? 現(xiàn)在編譯運行:

? ? ? ? demo run成功打印了仁连。

? ???????總結(jié)一下蓝角,?創(chuàng)建線程的第一種方式:繼承Thread類的步驟為:

? ??????1,定義類繼承Thread。

? ? ? ? 2使鹅,復寫Thread類中的run方法揪阶。

? ? ? ? 3,調(diào)用線程的start方法并徘,該方法有兩個作用:啟動線程遣钳,調(diào)用run方法。

? ? ? ? 冷靜下來思考一下麦乞,但是這跟我們以前調(diào)用方法的方式有什么區(qū)別呢蕴茴?怎么看不出來呀?

? ? ? ? 接下來我們讓它多運行一會兒姐直,寫了一個循環(huán)~

? ? ? ? 讓hello world也參與一下~

? ? ? ? 編譯運行:

????????我們分析一下它的執(zhí)行路徑:?

? ? ? ? 所以我們在打印結(jié)果的時候是交替打印的倦淀。

? ? ? ? 為什么是交替的呢?main線程和d線程它們倆不是同時執(zhí)行嗎声畏?

? ? ? ? 跟你講哦撞叽,真實情況下是不可能的。

? ? ? ? windows本身是一個多任務操作系統(tǒng)插龄,看上去它確實在同時執(zhí)行愿棋,其實真正的情況是,cpu在某一時刻下均牢,只能執(zhí)行一個程序糠雨。為什么看起來是同時執(zhí)行的呢?因為cpu在這些程序之間做著快速的切換徘跪,切換的速度是相當快的甘邀,快到你根本感覺不出來它在切換,所以你覺得它在同時執(zhí)行垮庐。

? ? ? ? 而進程中真正在執(zhí)行的是線程松邪,所以cpu在切換的是每一個進程中的線程。而一個進程中有多個線程的話哨查,cpu也要做切換呢逗抑。(這也是機器中程序開的越多越慢的原因)

? ? ? ? 我們現(xiàn)在就不說多進程啦,我們就說其中一個進程好啦解恰。

? ? ? ? 在這個例子中锋八,這一個進程中,就已經(jīng)有多個線程啦护盈。cpu執(zhí)行main一會兒挟纱,執(zhí)行d一會兒。那么這種情況腐宋,我們形象的把它稱之為紊服,多個線程在搶劫cpu資源檀轨。這只是一種形象的說法,其實是cpu說了算欺嗤。只是說“搶”更形象一點兒~

? ? ? ? #Java小劇場

? ? ? ? cpu:執(zhí)行main一會兒参萄,執(zhí)行main一會兒,好了好了煎饼,再執(zhí)行d一會兒讹挎,再執(zhí)行d一會兒,再執(zhí)行d一會兒吆玖,誒筒溃,好像都沒顧到main了,那我再執(zhí)行main一會兒好了沾乘。怜奖。。

? ? ? ? #

? ? ? ? 早期有一些病毒就是通過消耗cpu資源讓電腦死機的翅阵。它就是一直在搶用cpu資源歪玲,從而達到讓別人搶不著的效果。

? ? ? ? 再回到我們的例子中掷匠。

? ? ? ? 到這里main線程就結(jié)束啦滥崩,那這個進程會結(jié)束嗎?不會讹语。因為d線程還沒有結(jié)束夭委,只要d線程還在,這個進程就存在募强。

? ? ? ? 現(xiàn)在有了雙核、多核處理器崇摄,就可以實現(xiàn)同時運行了擎值,這個cpu處理這個,那個cpu處理那個逐抑。不過具體是怎么切換的鸠儿,我們現(xiàn)在暫時控制不了,可以學一下多核編程玩一下~

? ? ? ? 雙核以后誰是瓶頸厕氨?內(nèi)存进每。

? ? ? ? #Java小劇場

? ? ? ? 小楠老師在做一個一對三的高考沖刺班,她同時帶三個孩子命斧,一會給這個輔導田晚,一會給那個輔導,還算忙得過來国葬。這個時候又有一個人報名了贤徒,小楠老師忙不過來了芹壕,于是就又請了一位老師,這位新老師來帶新報名的這個孩子接奈。這樣踢涌,小楠老師和新老師可以同時帶四個孩子。

? ? ? ? 小楠老師的補習班空間不大序宦,四個孩子就剛好坐滿啦睁壁。其實新老師也可以再帶兩個孩子呢,這樣小楠老師和新老師就可以同時帶六個孩子互捌,達到最大的效率潘明。可是因為補習班太小疫剃,不能容納更多孩子钉疫,小楠老師和新老師還是只能帶四個孩子。

? ? ? ? #

? ? ? ? 現(xiàn)在雙核之后巢价,還有四核牲阁、八核,聽起來好膩害哦壤躲。但是可能會出現(xiàn)cpu想處理數(shù)據(jù)但沒數(shù)據(jù)處理的情況城菊。(沒有地方裝數(shù)據(jù)呀)

? ? ? ? 再回到剛剛的例子中。我們又多運行了幾次碉克,發(fā)現(xiàn)每次運行打印的順序都不同凌唬。

? ? ? ? 因為多個線程都在獲取cpu的執(zhí)行權(quán)。cpu執(zhí)行到誰漏麦,誰就運行客税。

? ? ? ? 明確一點,在某一個時刻撕贞,只能有一個程序在運行更耻。(多核除外)

? ? ? ? cpu在做著快速的切換,以達到看上去是同時運行的效果捏膨。

? ? ? ? 我們可以形象的把多線程的運行行為看做在互相搶奪cpu的執(zhí)行權(quán)秧均。

? ? ? ? 這就是多線程的一個特性:隨機性。誰搶到誰執(zhí)行号涯,至于執(zhí)行多長時間目胡,cpu說的算。

? ? ? ? 當然链快,也會出現(xiàn)這樣的情況誉己,hello world執(zhí)行完了,才執(zhí)行demo run久又,或者demo run執(zhí)行完了巫延,才想起來執(zhí)行hello world效五。這種情況是cpu切換得有點慢。哈哈~遲鈍的cpu~

? ? ? ? 再當然炉峰,在沒有被特意控制的情況下畏妖,不會出現(xiàn)cpu把一個全部執(zhí)行完再執(zhí)行另一個的情況。 因為cpu它在優(yōu)化資源疼阔,它得去快速的做著切換戒劫,才能實現(xiàn)同時運行的效果,否則會出現(xiàn)一個程序在執(zhí)行婆廊,另一個程序執(zhí)行不了迅细。

????04-多線程(線程練習)

? ? ? ? 練習:創(chuàng)建兩個線程,和主線程交替運行淘邻。

? ? ? ? 運行結(jié)果:

? ? ? ? 這樣寫會怎樣呢:

? ? ? ? 還是只有一個主線程在執(zhí)行茵典,另外兩個線程沒有開啟。

? ? ? ? 主線程先打印one run宾舅,再打印two run统阿,最后打印main。

? ? ? ? 這里我們的循環(huán)只有60次筹我,所以主線程運行一段程序的時候扶平,其他程序等待時間不會太長,但是如果是6000蔬蕊、60000次呢结澄?這個其他程序的等待時間就很長啦。

? ? ? ? 所以岸夯,建立多個線程麻献,多個程序就可以“同時”運行~

????05-多線程(線程運行狀態(tài))

? ? ? ? 線程的四種狀態(tài):

????06-多線程(獲取線程對象以及名稱)

? ? ? ? 我們來看看關于線程名稱的方法,有setName:

? ? ? ? getName:

? ? ? ? 我們用getName方法來獲取一下線程名稱猜扮。

? ? ? ? 依然用之前的那個例子~

? ? ? ? 編譯運行:

? ? ? ? 我們發(fā)現(xiàn)有Thread-1和Thread-0兩個名字赎瑰。

? ? ? ? 原來線程都有自己默認的名稱。

? ? ? ? Thread-編號 該編號從0開始破镰。

? ? ? ? 我們也可以改變線程的名稱,用setName方法就好啦压储。

? ? ? ? 不過查一下Thread的構(gòu)造函數(shù)鲜漩,發(fā)現(xiàn)線程初始化的時候就可以有名稱啦!

? ? ? ? 我們調(diào)用一下父類的構(gòu)造方法:

? ? ? ? 現(xiàn)在在創(chuàng)建它們的時候就給它們起一下名字:

? ? ? ? 編譯運行:

? ? ? ? 自定義線程名稱成功啦~

? ? ? ? 另外集惋,Thread類還為我們提供了一個方法:currentThread()孕似。

? ? ? ? 這個方法是靜態(tài)的,說明這個對象沒有訪問到對象的特有數(shù)據(jù)刮刑,用類名訪問就可以啦喉祭。

? ? ? ? 我們使用這個方法养渴,來獲得當前線程的名稱:

? ? ? ? 獲取成功~(運行截圖略,就和this.getName()運行結(jié)果一樣)

? ? ? ? 既然兩種方法運行結(jié)果一樣泛烙,它們有什么不同呢理卑?

? ? ? ? 試一下:

? ? ? ? 運行:

? ? ? ? 運行結(jié)果是true哦。所以它倆是一樣噠蔽氨。

? ? ? ? 那用this調(diào)用就行了呀藐唠,多簡單,用currentThread那么長鹉究,那么麻煩宇立。

? ? ? ? 不是的。this調(diào)用的方式并不通用自赔,只有在類的對象調(diào)用類中方法時才可以用則中方式調(diào)用妈嘹。而currentThread是標準通用方法,無論誰調(diào)用都可以用~

? ? ? ? 我們來復習一下:

? ? ? ? static Thread currentThread():獲取當前線程對象绍妨。

? ? ? ? getName():獲取線程名稱润脸。

? ? ? ? 設置線程名稱:setName()或者構(gòu)造函數(shù)。

? ? ? ? 還有一個小問題:

? ? ? ? Thread-0和Thread-1“同時”運行的時候痘绎,用的x是同一個嗎津函?

? ? ? ? 不是的。

? ? ? ? Thread-0建立的時候孤页,內(nèi)存中會為它分配一塊內(nèi)存空間尔苦,其中有一塊叫x;Thread-1建立的時候行施,內(nèi)存也會為它分配另一塊內(nèi)存空間允坚,其中也有一塊叫x。多個線程“同時”運行的時候蛾号,注意局部變量是每個內(nèi)存空間中都有一份哦稠项。

????07-多線程(售票的例子)

? ? ? ? 接下來,我們用一個事例來對第二種方法進行闡述鲜结。

? ? ? ? 需求:簡單的賣票程序展运。

? ? ? ? 多個窗口同時賣票。

? ? ? ? 現(xiàn)在4個窗口同時賣票:

? ? ? ? 運行一下精刷,發(fā)現(xiàn)分不清都是哪個窗口賣的:

? ? ? ? 打印一下線程的名字:

? ? ? ? 運行拗胜,我們發(fā)現(xiàn)了一個問題:

? ? ? ? 1、2怒允、3埂软、4號窗口都賣了1號票。一節(jié)車廂就100個座纫事,可是現(xiàn)在賣出了400個座勘畔。

? ? ? ? 問題在于所灸,創(chuàng)建一個對象,里面就有100張票炫七。

? ? ? ? 我們的解決方式:讓4個對象共享100張票爬立。

? ? ? ? 該用靜態(tài)啦!

? ? ? ? 運行:

? ? ? ? OK啦诉字。沒有重復賣票的啦懦尝。

? ? ? ? 但是,我們一般是不是不定義靜態(tài)呀壤圃?因為它的生命周期太長啦陵霉!

? ? ? ? 那怎么解決呢?

? ? ? ? 用一個對象來賣100張票:

? ? ? ? 運行:

? ? ? ? 是不是也賣完啦~

? ? ? ? 但是發(fā)現(xiàn)這些亂七八糟什么東西呀:

? ? ? ? 也就是說伍绳,線程已經(jīng)開啟了踊挠,并且調(diào)用start函數(shù),從開啟狀態(tài)進入了運行狀態(tài)冲杀。這個時候又調(diào)用了start函數(shù)效床,又進入運行狀態(tài),這就是無效的呀权谁。

? ? ? ? 該怎么解決呢剩檀?

? ? ? ? 快接著看下去~

????08-多線程(創(chuàng)建線程-實現(xiàn)Runnable接口)

? ? ? ? 解決這個問題,我們就需要引入第二種創(chuàng)建線程的方式了旺芽。

? ? ? ? 我們來看一下Runnable接口:

? ? ? ? 這個接口里面非常的爽呀沪猴,就一個方法:

? ? ? ? 我們來跟著示例代碼來寫~emmm...不太懂耶。

? ? ? ? 那慢慢一步一步分析著來~先讓Ticket類實現(xiàn)Runnable接口:

? ? ? ? 主函數(shù)中:

? ? ? ? 我們現(xiàn)在需要想辦法讓線程調(diào)用Ticket中的run采章,需要讓Ticket中的run和Thread創(chuàng)建的對象有關系运嗜!

? ? ? ? 我們需要在創(chuàng)建線程對象時就明確要運行什么代碼。

? ? ? ? Thread有一個構(gòu)造方法悯舟,比較特殊:

? ? ? ? 它可以接收Runnable接口類型的對象担租。

? ? ? ? 所以這就是我們要實現(xiàn)Runnable接口的原因,因為Thread類認識這個Runnable接口抵怎。

? ? ? ? 所以奋救,我們在new Thread方法的同時,就可以指定run方法所屬的對象反惕。

? ? ? ? 編譯運行:

? ? ? ? 搞定菠镇!

? ? ? ? 這就是創(chuàng)建線程的第二種方式:實現(xiàn)Runnable接口。

? ? ? ? 步驟:

? ? ? ? 1承璃,定義類實現(xiàn)Runnable接口。

? ? ? ? 2蚌本,覆蓋Runnable接口中的run方法盔粹。

? ? ? ? ? ? ? ? 將線程要運行的代碼存放在該run方法中隘梨。

? ? ? ? 3,通過Thread類建立線程對象舷嗡。

? ? ? ? 4轴猎,將Runnable接口的子類對象作為實際參數(shù)傳遞給Thread類的構(gòu)造函數(shù)。

? ? ? ? ? ? ? ? 為什么要將Runnable接口的子類對象傳遞給Thread的構(gòu)造函數(shù)进萄?

? ? ? ? ? ? ? ? 因為捻脖,自定義的run方法所屬的對象是Runnable接口的子類對象。

? ? ? ? ? ? ? ? 所以要讓線程去指定對象的run方法中鼠。就必須明確該run方法所屬的對象可婶。

? ? ? ? 5,調(diào)用Thread類的start方法開啟線程援雇,并調(diào)用Runnable接口子類的run方法矛渴。

? ? ? ? 那么,這兩種創(chuàng)建線程的方式惫搏,也就是實現(xiàn)方式和繼承方式有什么區(qū)別呢具温?

? ? ? ? 我們先講一下Runnable接口的由來:

? ? ? ? 左邊的Student類,沒有父類筐赔,它里面的run方法需要被多線程執(zhí)行铣猩,所以就繼承了Thread類。

? ? ? ? 可是茴丰,Student在演變的過程中达皿,抽取出來了一個父類Person,這個時候Student類中的run方法需要被多線程執(zhí)行较沪,但是因為它已經(jīng)有父類了鳞绕,而Java又不支持多繼承,所以無法再繼承Thread類尸曼。

? ? ? ? 這時们何,Java提供了一個Runnable接口來解決這個問題,“你可以不叫我爸爸控轿,我也可以幫你執(zhí)行代碼冤竹,只要你符合我的規(guī)則就行”,將這個功能抽取出來封裝到了Runnable接口中茬射。

? ? ? ? 這就是接口的由來鹦蠕。

? ? ? ? 因此,實現(xiàn)方式的好處:避免了單繼承的局限性在抛,把它作為了一種功能的擴展封裝在了接口中钟病。在定義線程時,建議使用實現(xiàn)方式。

? ? ? ? 而且這個構(gòu)造方法使用了多態(tài):

? ? ? ? 因為日后會出現(xiàn)什么樣的接口子類是無法預知的肠阱,所以它用了多態(tài)的形式票唆,你只要符合規(guī)則,它都可以用屹徘!你只要符合PCI的規(guī)則走趋,后期粗現(xiàn)什么樣的版本,它都可以幫你運行噪伊!

? ? ? ? 我們發(fā)現(xiàn)簿煌,Thread類本身也實現(xiàn)了Runnable接口:

? ? ? ? Runnable接口的定義,其實就是在確立線程要運行代碼所存放的位置鉴吹。

? ? ? ? 兩種創(chuàng)建線程的方式還有一個區(qū)別:

? ? ? ? 繼承Thread:線程代碼存放在Thread子類的run方法中姨伟。

? ? ? ? 實現(xiàn)Runnable:線程代碼存放在接口子類的run方法中。

? ? ? ? 它們代碼的存放位置不一樣拙寡。

? ? ? ? 當然授滓,如果你的類沒有父類,用第一種方式也是完全可以的肆糕。

????09-多線程(多線程的安全問題)

? ? ? ? 現(xiàn)在只剩最后一張票了般堆,然后4個窗口都拿到了執(zhí)行資格,在等待執(zhí)行權(quán)诚啃,最后執(zhí)行權(quán)比如說給了0號淮摔,0號賣出后執(zhí)行權(quán)比如給了1號,這個時候1再繼續(xù)執(zhí)行票數(shù)就為負了始赎,這顯然不符合常理和橙。我們的程序有bug啦!?

? ? ? ? 我們現(xiàn)在模擬一下這個過程造垛,讓我們真實的看到這個現(xiàn)象魔招。

? ? ? ? 怎么做呢?

? ? ? ? 那怎么讓它睡一下呢五辽?

? ? ? ? 看一下sleep方法:

? ? ? ? 我們看一下這個方法的特點:

? ? ? ? 它是靜態(tài)的办斑,沒有訪問到對象的特有數(shù)據(jù),并且它拋出了異常杆逗。

? ? ? ? 話不多說乡翅,寫起來:

? ? ? ? 因為Ticket實現(xiàn)了Runnable接口,而這個接口并未拋出異常罪郊,所以Ticket也不能拋出異常蠕蚜,所以只能try哦。

? ? ? ? 運行一下:

? ? ? ? 剛剛那個問題就出現(xiàn)啦悔橄。

? ? ? ? 通過分析靶累,發(fā)現(xiàn)腺毫,打印出0,-1挣柬,-2等錯票拴曲。

? ? ? ? 多線程的運行出現(xiàn)了安全問題。

? ? ? ? 安全問題最可怕辣凛忿!

? ? ? ? 多線程中一定要小心安全問題,一旦產(chǎn)生就非常要命竞川。

? ? ? ? 問題的原因:

? ? ? ? 當多條語句在操作同一個線程共享數(shù)據(jù)時店溢,一個線程對多條語句只執(zhí)行了一部分,還沒有執(zhí)行完委乌,另一個線程參與進來執(zhí)行床牧,導致了共享數(shù)據(jù)的錯誤。

? ? ? ? 解決辦法:

? ? ? ? 對多條操作共享數(shù)據(jù)的語句遭贸,只能讓一個線程都執(zhí)行完戈咳,在執(zhí)行過程中,其他過程不可以參與執(zhí)行壕吹。

? ? ? ? Java對于多線程的安全問題提供了專業(yè)的解決方式著蛙。

? ? ? ? 就是同步代碼塊。

? ? ? ? synchronized(對象)

? ? ? ? {

? ? ? ? ? ? ? ? 需要被同步的代碼

? ? ? ? }

? ? ? ? 寫起來~

? ? ? ? 運行看一下效果:

? ? ? ? OK啦耳贬!

? ??10-多線程(多線程同步代碼塊)

? ? ? ? 在上節(jié)課中踏堡,這里有個對象:

? ? ? ? 這個對象如同鎖,持有鎖的線程可以在同步中執(zhí)行咒劲。

? ? ? ? 沒有持有鎖的線程顷蟆,即使獲得了cpu的執(zhí)行權(quán),也進不去腐魂,因為沒有獲取鎖帐偎。

? ? ? ? 火車上的衛(wèi)生間就是一個經(jīng)典的的例子。

? ? ? ? 同步的前提:

? ? ? ? 1蛔屹,必須要有兩個或者兩個以上的線程才需要同步削樊。(就你一個人用這個衛(wèi)生間,就不需要鎖門啦)

? ? ? ? 2判导,必須是多個線程使用同一個鎖才需要同步嫉父。(多個人使用的是同一個衛(wèi)生間)

? ? ? ? 必須保證同步中只能有一個線程在運行。

? ? ? ? 同步的好處:

? ? ? ? 解決了多線程的安全問題眼刃。

? ? ? ? 不過它也有弊端:雖然解決了問題绕辖,但是執(zhí)行的時候每次都要判斷這個鎖,所以較為消耗資源擂红。(越安全越麻煩)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仪际,一起剝皮案震驚了整個濱河市围小,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌树碱,老刑警劉巖肯适,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莲绰,死亡現(xiàn)場離奇詭異盆昙,居然都是意外死亡贺氓,警方通過查閱死者的電腦和手機级野,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門鲫尊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逊彭,“玉大人然磷,你說我怎么就攤上這事紫谷≌跏洌” “怎么了纬凤?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長撩嚼。 經(jīng)常有香客問我停士,道長,這世上最難降的妖魔是什么完丽? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任恋技,我火速辦了婚禮,結(jié)果婚禮上舰涌,老公的妹妹穿的比我還像新娘猖任。我一直安慰自己,他們只是感情好瓷耙,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布朱躺。 她就那樣靜靜地躺著,像睡著了一般搁痛。 火紅的嫁衣襯著肌膚如雪长搀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天鸡典,我揣著相機與錄音源请,去河邊找鬼。 笑死彻况,一個胖子當著我的面吹牛谁尸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纽甘,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼良蛮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了悍赢?” 一聲冷哼從身側(cè)響起决瞳,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤货徙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后皮胡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痴颊,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年屡贺,在試婚紗的時候發(fā)現(xiàn)自己被綠了蠢棱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡甩栈,死狀恐怖裳扯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谤职,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布亿鲜,位于F島的核電站允蜈,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蒿柳。R本人自食惡果不足惜饶套,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望垒探。 院中可真熱鬧妓蛮,春花似錦、人聲如沸圾叼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夷蚊。三九已至构挤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惕鼓,已是汗流浹背筋现。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留箱歧,地道東北人矾飞。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像呀邢,于是被迫代替她去往敵國和親洒沦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

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

  • 進程和線程 進程 所有運行中的任務通常對應一個進程,當一個程序進入內(nèi)存運行時,即變成一個進程.進程是處于運行過程中...
    勝浩_ae28閱讀 5,085評論 0 23
  • 進程和線程 進程 所有運行中的任務通常對應一個進程,當一個程序進入內(nèi)存運行時,即變成一個進程.進程是處于運行過程中...
    小徐andorid閱讀 2,797評論 3 53
  • 本文主要講了java中多線程的使用方法驼鹅、線程同步微谓、線程數(shù)據(jù)傳遞森篷、線程狀態(tài)及相應的一些線程函數(shù)用法、概述等豺型。在這之前...
    4ea0af17fd67閱讀 587評論 2 17
  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,952評論 1 18
  • 單任務 單任務的特點是排隊執(zhí)行仲智,也就是同步,就像再cmd輸入一條命令后姻氨,必須等待這條命令執(zhí)行完才可以執(zhí)行下一條命令...
    Steven1997閱讀 1,166評論 0 6