Java學(xué)習(xí)筆記(4)——并發(fā)基礎(chǔ)

前言

當(dāng)我們使用計(jì)算機(jī)時(shí),可以同時(shí)做許多事情杭隙,例如一邊打游戲一邊聽(tīng)音樂(lè)哟绊。這是因?yàn)椴僮飨到y(tǒng)支持并發(fā)任務(wù),從而使得這些工作得以同時(shí)進(jìn)行痰憎。

那么提出一個(gè)問(wèn)題:如果我們要實(shí)現(xiàn)一個(gè)程序能一邊聽(tīng)音樂(lè)一邊玩游戲怎么實(shí)現(xiàn)呢匿情?

提出的問(wèn)題

我們使用了循環(huán)來(lái)模擬過(guò)程,因?yàn)椴シ乓魳?lè)和打游戲都是連續(xù)的信殊,但是結(jié)果卻不盡人意,因?yàn)楹瘮?shù)體總是要執(zhí)行完之后才能返回汁果。那么到底怎么解決這個(gè)問(wèn)題涡拘?下面來(lái)說(shuō)。

并行與并發(fā)

并行性和并發(fā)性是既相似又有區(qū)別的兩個(gè)概念据德。

并行性是指兩個(gè)或多個(gè)事件在同一時(shí)刻發(fā)生鳄乏。而并發(fā)性是指連個(gè)或多個(gè)事件在同一時(shí)間間隔內(nèi)發(fā)生。在多道程序環(huán)境下棘利,并發(fā)性是指在一段時(shí)間內(nèi)宏觀上有多個(gè)程序在同時(shí)運(yùn)行橱野,但在單處理機(jī)環(huán)境下(一個(gè)處理器),每一時(shí)刻卻僅能有一道程序執(zhí)行善玫,故微觀上這些程序只能是分時(shí)地交替執(zhí)行水援。例如,在1秒鐘時(shí)間內(nèi),0-15ms程序A運(yùn)行蜗元;15-30ms程序B運(yùn)行或渤;30-45ms程序C運(yùn)行;45-60ms程序D運(yùn)行奕扣,因此可以說(shuō)薪鹦,在1秒鐘時(shí)間間隔內(nèi),宏觀上有四道程序在同時(shí)運(yùn)行惯豆,但微觀上池磁,程序A、B楷兽、C地熄、D是分時(shí)地交替執(zhí)行的。

如果在計(jì)算機(jī)系統(tǒng)中有多個(gè)處理機(jī)拄养,這些可以并發(fā)執(zhí)行的程序就可以被分配到多個(gè)處理機(jī)上离斩,實(shí)現(xiàn)并發(fā)執(zhí)行,即利用每個(gè)處理機(jī)愛(ài)處理一個(gè)可并發(fā)執(zhí)行的程序瘪匿。這樣跛梗,多個(gè)程序便可以同時(shí)執(zhí)行。以此就能提高系統(tǒng)中的資源利用率棋弥,增加系統(tǒng)的吞吐量核偿。

并發(fā)和并行

進(jìn)程和線程

進(jìn)程是指一個(gè)內(nèi)存中運(yùn)行的應(yīng)用程序。一個(gè)應(yīng)用程序可以同時(shí)啟動(dòng)多個(gè)進(jìn)程顽染,那么上面的問(wèn)題就有了解決的思路:我們啟動(dòng)兩個(gè)進(jìn)程漾岳,一個(gè)用來(lái)打游戲,一個(gè)用來(lái)播放音樂(lè)粉寞。這當(dāng)然是一種解決方案尼荆,但是想象一下,如果一個(gè)應(yīng)用程序需要執(zhí)行的任務(wù)非常多唧垦,例如LOL游戲吧捅儒,光是需要播放的音樂(lè)就有非常多,人物本身的語(yǔ)音振亮,技能的音效暴凑,游戲的背景音樂(lè)浮驳,塔攻擊的聲音等等等盗尸,還不用說(shuō)游戲本身选脊,就光播放音樂(lè)就需要?jiǎng)?chuàng)建許多許多的進(jìn)程,而進(jìn)程本身是一種非常消耗資源的東西褒搔,這樣的設(shè)計(jì)顯然是不合理的阶牍。更何況大多數(shù)的操作系統(tǒng)都不需要一個(gè)進(jìn)程訪問(wèn)其他進(jìn)程的內(nèi)存空間喷面,也就是說(shuō),進(jìn)程之間的通信很不方便荸恕,此時(shí)我們就得引入“線程”這門技術(shù)乖酬,來(lái)解決這個(gè)問(wèn)題。

線程是指進(jìn)程中的一個(gè)執(zhí)行任務(wù)(控制單元)融求,一個(gè)進(jìn)程可以同時(shí)并發(fā)運(yùn)行多個(gè)線程咬像。打開(kāi)我們的任務(wù)管理器,在【查看】里面點(diǎn)擊【選擇列】生宛,有一個(gè)線程數(shù)的勾選項(xiàng)县昂,找到并勾選,可以看到:

任務(wù)管理器

進(jìn)程和線程的區(qū)別:

進(jìn)程:有獨(dú)立的內(nèi)存空間陷舅,進(jìn)程中的數(shù)據(jù)存放空間(堆空間和椀拐茫空間)是獨(dú)立的,至少有一個(gè)線程莱睁。

線程:堆空間是共享的待讳,棧空間是獨(dú)立的仰剿,線程消耗的資源也比進(jìn)程小创淡,相互之間可以影響的,又稱為輕型進(jìn)程或進(jìn)程元南吮。

因?yàn)橐粋€(gè)進(jìn)程中的多個(gè)線程是并發(fā)運(yùn)行的琳彩,那么從微觀角度上考慮也是有先后順序的,那么哪個(gè)線程執(zhí)行完全取決于CPU調(diào)度器(JVM來(lái)調(diào)度)部凑,程序員是控制不了的露乏。我們可以把多線程并發(fā)性看作是多個(gè)線程在瞬間搶CPU資源,誰(shuí)搶到資源誰(shuí)就運(yùn)行涂邀,這也造就了多線程的隨機(jī)性瘟仿。下面我們將看到更生動(dòng)的例子。

Java程序的進(jìn)程(Java的一個(gè)程序運(yùn)行在系統(tǒng)中)里至少包含主線程和垃圾回收線程(后臺(tái)線程):

你可以簡(jiǎn)單的這樣認(rèn)為比勉,但實(shí)際上有四個(gè)線程(了解就好):
[1] main——main線程猾骡,用戶程序入口
[2] Reference Handler——清除Reference的線程
[3] Finalizer——調(diào)用對(duì)象finalize方法的線程
[4] Signal Dispatcher——分發(fā)處理發(fā)送給JVM信號(hào)的線程

多線程的優(yōu)勢(shì):

盡管面臨很多挑戰(zhàn),多線程有一些優(yōu)點(diǎn)使得它一直被使用敷搪。這些優(yōu)點(diǎn)是:

  • 資源利用率更好
  • 程序設(shè)計(jì)在某些情況下更簡(jiǎn)單
  • 程序響應(yīng)更快

(1)資源利用率更好

想象一下,一個(gè)應(yīng)用程序需要從本地文件系統(tǒng)中讀取和處理文件的情景幢哨。比方說(shuō)赡勘,從磁盤讀取一個(gè)文件需要5秒,處理一個(gè)文件需要2秒捞镰。處理兩個(gè)文件則需要:

1| 5秒讀取文件A
2| 2秒處理文件A
3| 5秒讀取文件B
4| 2秒處理文件B
5| ---------------------
6| 總共需要14秒

從磁盤中讀取文件的時(shí)候闸与,大部分的CPU時(shí)間用于等待磁盤去讀取數(shù)據(jù)毙替。在這段時(shí)間里,CPU非常的空閑践樱。它可以做一些別的事情厂画。通過(guò)改變操作的順序,就能夠更好的使用CPU資源拷邢「ぴ海看下面的順序:

1| 5秒讀取文件A
2| 5秒讀取文件B + 2秒處理文件A
3| 2秒處理文件B
4| ---------------------
5| 總共需要12秒

CPU等待第一個(gè)文件被讀取完。然后開(kāi)始讀取第二個(gè)文件瞭稼。當(dāng)?shù)诙募诒蛔x取的時(shí)候忽洛,CPU會(huì)去處理第一個(gè)文件。記住环肘,在等待磁盤讀取文件的時(shí)候欲虚,CPU大部分時(shí)間是空閑的。

總的說(shuō)來(lái)悔雹,CPU能夠在等待IO的時(shí)候做一些其他的事情复哆。這個(gè)不一定就是磁盤IO。它也可以是網(wǎng)絡(luò)的IO腌零,或者用戶輸入梯找。通常情況下,網(wǎng)絡(luò)和磁盤的IO比CPU和內(nèi)存的IO慢的多莱没。

(2)程序設(shè)計(jì)更簡(jiǎn)單

在單線程應(yīng)用程序中初肉,如果你想編寫(xiě)程序手動(dòng)處理上面所提到的讀取和處理的順序,你必須記錄每個(gè)文件讀取和處理的狀態(tài)饰躲。相反牙咏,你可以啟動(dòng)兩個(gè)線程,每個(gè)線程處理一個(gè)文件的讀取和操作嘹裂。線程會(huì)在等待磁盤讀取文件的過(guò)程中被阻塞妄壶。在等待的時(shí)候,其他的線程能夠使用CPU去處理已經(jīng)讀取完的文件寄狼。其結(jié)果就是丁寄,磁盤總是在繁忙地讀取不同的文件到內(nèi)存中。這會(huì)帶來(lái)磁盤和CPU利用率的提升泊愧。而且每個(gè)線程只需要記錄一個(gè)文件伊磺,因此這種方式也很容易編程實(shí)現(xiàn)。

(3)程序響應(yīng)更快

有時(shí)我們會(huì)編寫(xiě)一些較為復(fù)雜的代碼(這里的復(fù)雜不是說(shuō)復(fù)雜的算法删咱,而是復(fù)雜的業(yè)務(wù)邏輯)屑埋,例如,一筆訂單的創(chuàng)建痰滋,它包括插入訂單數(shù)據(jù)摘能、生成訂單趕快找续崖、發(fā)送郵件通知賣家和記錄貨品銷售數(shù)量等。用戶從單擊“訂購(gòu)”按鈕開(kāi)始团搞,就要等待這些操作全部完成才能看到訂購(gòu)成功的結(jié)果严望。但是這么多業(yè)務(wù)操作,如何能夠讓其更快地完成呢逻恐?

在上面的場(chǎng)景中像吻,可以使用多線程技術(shù),即將數(shù)據(jù)一致性不強(qiáng)的操作派發(fā)給其他線程處理(也可以使用消息隊(duì)列)梢莽,如生成訂單快照萧豆、發(fā)送郵件等。這樣做的好處是響應(yīng)用戶請(qǐng)求的線程能夠盡可能快地處理完成昏名,縮短了響應(yīng)時(shí)間涮雷,提升了用戶體驗(yàn)。

多線程的還有一些優(yōu)勢(shì)也顯而易見(jiàn):

  • ① 進(jìn)程之前不能共享內(nèi)存轻局,而線程之間共享內(nèi)存(堆內(nèi)存)則很簡(jiǎn)單洪鸭。
  • ② 系統(tǒng)創(chuàng)建進(jìn)程時(shí)需要為該進(jìn)程重新分配系統(tǒng)資源,創(chuàng)建線程則代價(jià)小很多,因此實(shí)現(xiàn)多任務(wù)并發(fā)時(shí),多線程效率更高.
  • ③ Java語(yǔ)言本身內(nèi)置多線程功能的支持,而不是單純第作為底層系統(tǒng)的調(diào)度方式,從而簡(jiǎn)化了多線程編程.

上下文切換

即使是單核處理器也支持多線程執(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í)執(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ū)之前,大腦必須先記住這本書(shū)獨(dú)到了多少頁(yè)的多少行矾湃,等查完單詞之后亡脑,能夠繼續(xù)讀這本書(shū)。這樣的切換是會(huì)影響讀書(shū)效率的,同樣上下文切換也會(huì)影響多線程的執(zhí)行速度远豺。

創(chuàng)建線程的兩種方式

繼承Thead類:

繼承Thread類

運(yùn)行結(jié)果發(fā)現(xiàn)打游戲和播放音樂(lè)交替出現(xiàn),說(shuō)明已經(jīng)成功了坞嘀。

實(shí)現(xiàn)Runnable接口:

實(shí)現(xiàn)Runnable接口

也能完成效果躯护。

以上就是傳統(tǒng)的兩種創(chuàng)建線程的方式,事實(shí)上還有第三種丽涩,我們后邊再講棺滞。

多線程一定快嗎?

先來(lái)一段代碼矢渊,通過(guò)并行和串行來(lái)分別執(zhí)行累加操作继准,分析:下面的代碼并發(fā)執(zhí)行一定比串行執(zhí)行快嗎?

多線程一定快嗎矮男?

以下是我測(cè)試的結(jié)果移必,可以看出,當(dāng)不超過(guò)1百萬(wàn)的時(shí)候毡鉴,并行是明顯比串行要慢的崔泵,為什么并發(fā)執(zhí)行的速度會(huì)比串行慢呢?這是因?yàn)榫€程有創(chuàng)建和上下文切換的開(kāi)銷猪瞬。

測(cè)試結(jié)果

繼承Thread類還是實(shí)現(xiàn)Runnable接口憎瘸?

吃蘋(píng)果比賽

想象一個(gè)這樣的例子:給出一共50個(gè)蘋(píng)果,讓三個(gè)同學(xué)一起來(lái)吃陈瘦,并且給蘋(píng)果編上號(hào)碼幌甘,讓他們吃的時(shí)候順便要說(shuō)出蘋(píng)果的編號(hào):

吃蘋(píng)果比賽

運(yùn)行結(jié)果可以看到,使用繼承方式實(shí)現(xiàn)痊项,每一個(gè)線程都吃了50個(gè)蘋(píng)果锅风。這樣的結(jié)果顯而易見(jiàn):是因?yàn)轱@式地創(chuàng)建了三個(gè)不同的Person對(duì)象,而每個(gè)對(duì)象在堆空間中有獨(dú)立的區(qū)域來(lái)保存定義好的50個(gè)蘋(píng)果线婚。

而使用實(shí)現(xiàn)方式則滿足要求遏弱,這是因?yàn)槿齻€(gè)線程共享了同一個(gè)Apple對(duì)象,而對(duì)象中的num數(shù)量是一定的漱逸。

所以可以簡(jiǎn)單總結(jié)出繼承方式和實(shí)現(xiàn)方式的區(qū)別:


兩種方式的區(qū)別

對(duì)于這兩種方式哪種好并沒(méi)有一個(gè)確定的答案,它們都能滿足要求游沿。就我個(gè)人意見(jiàn)枣宫,我更傾向于實(shí)現(xiàn)Runnable接口這種方法洋幻。因?yàn)榫€程池可以有效的管理實(shí)現(xiàn)了Runnable接口的線程,如果線程池滿了翅娶,新的線程就會(huì)排隊(duì)等候執(zhí)行文留,直到線程池空閑出來(lái)為止。而如果線程是通過(guò)實(shí)現(xiàn)Thread子類實(shí)現(xiàn)的竭沫,這將會(huì)復(fù)雜一些燥翅。

有時(shí)我們要同時(shí)融合實(shí)現(xiàn)Runnable接口和Thread子類兩種方式。例如蜕提,實(shí)現(xiàn)了Thread子類的實(shí)例可以執(zhí)行多個(gè)實(shí)現(xiàn)了Runnable接口的線程森书。一個(gè)典型的應(yīng)用就是線程池。

常見(jiàn)的錯(cuò)誤:調(diào)用run()方法而非start()方法

創(chuàng)建并運(yùn)行一個(gè)線程所犯的常見(jiàn)錯(cuò)誤是調(diào)用線程的run()方法而非start()方法贯溅,如下所示:

1| Thread newThread = new Thread(MyRunnable());
2| newThread.run();  //should be start();

起初你并不會(huì)感覺(jué)到有什么不妥拄氯,因?yàn)閞un()方法的確如你所愿的被調(diào)用了。但是它浅,事實(shí)上,run()方法并非是由剛創(chuàng)建的新線程所執(zhí)行的译柏,而是被創(chuàng)建新線程的當(dāng)前線程所執(zhí)行了。也就是被執(zhí)行上面兩行代碼的線程所執(zhí)行的姐霍。想要讓創(chuàng)建的新線程執(zhí)行run()方法鄙麦,必須調(diào)用新線程的start方法。

吃蘋(píng)果比賽的問(wèn)題:線程不安全問(wèn)題

盡管镊折,Java并不保證線程的順序執(zhí)行胯府,具有隨機(jī)性,但吃蘋(píng)果比賽的案例運(yùn)行多次也并沒(méi)有發(fā)現(xiàn)什么太大的問(wèn)題恨胚。這并不是因?yàn)槌绦驔](méi)有問(wèn)題骂因,而只是問(wèn)題出現(xiàn)的不夠明顯,為了讓問(wèn)題更加明顯赃泡,我們使用Thread.sleep()方法(經(jīng)常用來(lái)模擬網(wǎng)絡(luò)延遲)來(lái)讓線程休息10ms寒波,讓其他線程去搶資源。(注意:在程序中并不是使用Thread.sleep(10)之后,程序才出現(xiàn)問(wèn)題,而是使用之后,問(wèn)題更明顯.)

吃蘋(píng)果比賽中的問(wèn)題

為什么會(huì)出現(xiàn)這樣的錯(cuò)誤呢升熊?

先來(lái)分析第一種錯(cuò)誤:為什么會(huì)吃重復(fù)的蘋(píng)果呢俄烁?就拿B和C都吃了編號(hào)為47的蘋(píng)果為例吧:

  • ① A線程拿到了編號(hào)為48的蘋(píng)果,打印輸出然后讓num減1级野,睡眠10ms页屠,此時(shí)num為47。
  • ② 這時(shí)B和C同時(shí)都拿到了編號(hào)為47的蘋(píng)果,打印輸出辰企,在其中一個(gè)線程作出了減一操作的時(shí)候风纠,A線程從睡眠中醒過(guò)來(lái),拿到了編號(hào)為46的蘋(píng)果牢贸,然后輸出议忽。在這期間并沒(méi)有任何操作不允許B和C線程不能拿到同一個(gè)編號(hào)的蘋(píng)果,之前沒(méi)有明顯的錯(cuò)誤僅僅可能只是因?yàn)檫\(yùn)行速度太快了十减。

再來(lái)分析第二種錯(cuò)誤:照理來(lái)說(shuō)只應(yīng)該存在1-50編號(hào)的蘋(píng)果,可是0和-1是怎么出現(xiàn)的呢愤估?

  • ① 當(dāng)num=1的時(shí)候帮辟,A,B玩焰,C三個(gè)線程同時(shí)進(jìn)入了try語(yǔ)句進(jìn)行睡眠由驹。
  • ② C線程先醒過(guò)來(lái),輸出了編號(hào)為1的蘋(píng)果昔园,然后讓num減一蔓榄,當(dāng)C線程醒過(guò)來(lái)的時(shí)候發(fā)現(xiàn)num為0了。
  • ③ A線程醒過(guò)來(lái)一看默刚,0都沒(méi)有了甥郑,只有-1了。

歸根結(jié)底是因?yàn)闆](méi)有任何操作來(lái)限制線程來(lái)獲取相同的資源并對(duì)他們進(jìn)行操作荤西,這就造成了線程安全性問(wèn)題澜搅。

如果我們把打印和減一的操作分成兩個(gè)步驟,會(huì)更加明顯:


拆成兩個(gè)步驟

ABC三個(gè)線程同時(shí)打印了50的蘋(píng)果邪锌,然后同時(shí)做出減一操作勉躺。

像這樣的原子操作,是不允許分步驟進(jìn)行的觅丰,必須保證同步進(jìn)行饵溅,不然可能會(huì)引發(fā)不可設(shè)想的后果。

要解決上述多線程并發(fā)訪問(wèn)一個(gè)資源的安全性問(wèn)題妇萄,就需要引入線程同步的概念蜕企。

線程同步

多個(gè)執(zhí)行線程共享一個(gè)資源的情景,是最常見(jiàn)的并發(fā)編程情景之一嚣伐。為了解決訪問(wèn)共享資源錯(cuò)誤或數(shù)據(jù)不一致的問(wèn)題糖赔,人們引入了臨界區(qū)的概念:用以訪問(wèn)共享資源的代碼塊,這個(gè)代碼塊在同一時(shí)間內(nèi)只允許一個(gè)線程執(zhí)行轩端。

為了幫助編程人員實(shí)現(xiàn)這個(gè)臨界區(qū)放典,Java(以及大多數(shù)編程語(yǔ)言)提供了同步機(jī)制,當(dāng)一個(gè)線程試圖訪問(wèn)一個(gè)臨界區(qū)時(shí),它將使用一種同步機(jī)制來(lái)查看是不是已經(jīng)有其他線程進(jìn)入臨界區(qū)奋构。如果沒(méi)有其他線程進(jìn)入臨界區(qū)壳影,他就可以進(jìn)入臨界區(qū)。如果已經(jīng)有線程進(jìn)入了臨界區(qū)弥臼,它就被同步機(jī)制掛起宴咧,直到進(jìn)入的線程離開(kāi)這個(gè)臨界區(qū)。如果在等待進(jìn)入臨界區(qū)的線程不止一個(gè)径缅,JVM會(huì)選擇其中的一個(gè)掺栅,其余的將繼續(xù)等待。

synchronized關(guān)鍵字

如果一個(gè)對(duì)象已用synchronized關(guān)鍵字聲明纳猪,那么只有一個(gè)執(zhí)行線程被允許訪問(wèn)它氧卧。使用synchronized的好處顯而易見(jiàn):保證了多線程并發(fā)訪問(wèn)時(shí)的同步操作,避免線程的安全性問(wèn)題氏堤。但是壞處是:使用synchronized的方法/代碼塊的性能比不用要低一些沙绝。所以好的做法是:盡量減小synchronized的作用域。

我們還是先來(lái)解決吃蘋(píng)果的問(wèn)題鼠锈,考慮一下synchronized關(guān)鍵字應(yīng)該加在哪里呢闪檬?


synchronized應(yīng)放在哪里?

發(fā)現(xiàn)如果還再把synchronized關(guān)鍵字加在if里面的話购笆,0和-1又會(huì)出來(lái)了粗悯。這其實(shí)是因?yàn)楫?dāng)ABC同是進(jìn)入到if語(yǔ)句中,等待臨界區(qū)釋放的時(shí)同欠,拿到1編號(hào)的線程已經(jīng)又把num減一操作了为黎,而此時(shí)最后一個(gè)等待臨界區(qū)的進(jìn)程拿到的就會(huì)是-1了。

同步鎖(Lock)

Lock機(jī)制提供了比synchronized代碼塊和synchronized方法更廣泛的鎖定操作,同步代碼塊/同步方法具有的功能Lock都有,除此之外更強(qiáng)大,更體現(xiàn)面向?qū)ο蟆?/p>

摘自JDK1.6中文版說(shuō)明的代碼

參考資料:


歡迎轉(zhuǎn)載行您,轉(zhuǎn)載請(qǐng)注明出處铭乾!
簡(jiǎn)書(shū)ID:@我沒(méi)有三顆心臟
github:wmyskxz
歡迎關(guān)注公眾微信號(hào):wmyskxz
分享自己的學(xué)習(xí) & 學(xué)習(xí)資料 & 生活
想要交流的朋友也可以加qq群:3382693

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市娃循,隨后出現(xiàn)的幾起案子炕檩,更是在濱河造成了極大的恐慌,老刑警劉巖捌斧,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笛质,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡捞蚂,警方通過(guò)查閱死者的電腦和手機(jī)妇押,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)姓迅,“玉大人敲霍,你說(shuō)我怎么就攤上這事俊马。” “怎么了肩杈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵柴我,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我扩然,道長(zhǎng)艘儒,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任夫偶,我火速辦了婚禮界睁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘兵拢。我一直安慰自己晕窑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布卵佛。 她就那樣靜靜地躺著,像睡著了一般敞斋。 火紅的嫁衣襯著肌膚如雪截汪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天植捎,我揣著相機(jī)與錄音衙解,去河邊找鬼。 笑死焰枢,一個(gè)胖子當(dāng)著我的面吹牛蚓峦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播济锄,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼暑椰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了荐绝?” 一聲冷哼從身側(cè)響起一汽,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎低滩,沒(méi)想到半個(gè)月后召夹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恕沫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年监憎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婶溯。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鲸阔,死狀恐怖偷霉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情隶债,我是刑警寧澤腾它,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站死讹,受9級(jí)特大地震影響瞒滴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赞警,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一妓忍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧愧旦,春花似錦世剖、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至琼蚯,卻和暖如春酬凳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背遭庶。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工宁仔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人峦睡。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓翎苫,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親榨了。 傳聞我的和親對(duì)象是個(gè)殘疾皇子煎谍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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

  • Java-Review-Note——4.多線程 標(biāo)簽: JavaStudy PS:本來(lái)是分開(kāi)三篇的,后來(lái)想想還是整...
    coder_pig閱讀 1,649評(píng)論 2 17
  • 一龙屉、進(jìn)程和線程 進(jìn)程 進(jìn)程就是一個(gè)執(zhí)行中的程序?qū)嵗豢欤總€(gè)進(jìn)程都有自己獨(dú)立的一塊內(nèi)存空間,一個(gè)進(jìn)程中可以有多個(gè)線程叔扼。...
    阿敏其人閱讀 2,612評(píng)論 0 13
  • 前言:雖然自己平時(shí)都在用多線程事哭,也能完成基本的工作需求,但總覺(jué)得瓜富,還是對(duì)線程沒(méi)有一個(gè)系統(tǒng)的概念鳍咱,所以,查閱了一些資...
    justCode_閱讀 708評(píng)論 0 9
  • 本人在談戀愛(ài)打游戲的時(shí)代加入了一個(gè)業(yè)余合唱團(tuán),雖是業(yè)余抒抬,可是水平并不低织中,隊(duì)員中一半以上有專業(yè)功底抗悍,省部級(jí)比賽常獲前...
    清水一點(diǎn)通閱讀 540評(píng)論 0 1
  • 2016年進(jìn)入倒計(jì)時(shí)一個(gè)月,緬懷過(guò)去串述,淚流滿面皿淋。 感動(dòng)或听「校回家次數(shù)還不如大學(xué)的多渔彰,盡管距離近了,卻嫌棄坐車麻煩推正,兩個(gè)...
    moufei007閱讀 144評(píng)論 0 0