java線程-看這一篇就夠了

前言

如果對什么是線程、什么是進(jìn)程仍存有疑惑否纬,請先Google之吕晌,因為這兩個概念不在本文的范圍之內(nèi)。

基本概念

用多線程只有一個目的临燃,那就是更好的利用cpu的資源睛驳,因為所有的多線程代碼都可以用單線程來實現(xiàn)。說這個話其實只有一半對膜廊,因為反應(yīng)“多角色”的程序代碼乏沸,最起碼每個角色要給他一個線程吧,否則連實際場景都無法模擬爪瓜,當(dāng)然也沒法說能用單線程來實現(xiàn):比如最常見的“生產(chǎn)者蹬跃,消費者模型”。

很多人都對其中的一些概念不夠明確铆铆,如同步蝶缀、并發(fā)等等,讓我們先建立一個數(shù)據(jù)字典薄货,以免產(chǎn)生誤會翁都。

多線程:指的是這個程序(一個進(jìn)程)運行時產(chǎn)生了不止一個線程

并行與并發(fā):

并行:多個cpu實例或者多臺機器同時執(zhí)行一段處理邏輯,是真正的同時谅猾。

并發(fā):通過cpu調(diào)度算法柄慰,讓用戶看上去同時執(zhí)行鳍悠,實際上從cpu操作層面不是真正的同時。并發(fā)往往在場景中有公用的資源坐搔,那么針對這個公用的資源往往產(chǎn)生瓶頸贼涩,我們會用TPS或者QPS來反應(yīng)這個系統(tǒng)的處理能力。

?

線程安全:經(jīng)常用來描繪一段代碼薯蝎。指在并發(fā)的情況之下遥倦,該代碼經(jīng)過多線程使用,線程的調(diào)度順序不影響任何結(jié)果占锯。這個時候使用多線程袒哥,我們只需要關(guān)注系統(tǒng)的內(nèi)存,cpu是不是夠用即可消略。反過來堡称,線程不安全就意味著線程的調(diào)度順序會影響最終結(jié)果,如不加事務(wù)的轉(zhuǎn)賬代碼:

void transferMoney(User from, User to, float amount){

? ?to.setMoney(to.getBalance() + amount);

? ?from.setMoney(from.getBalance() - amount);

}

同步:Java中的同步指的是通過人為的控制和調(diào)度艺演,保證共享資源的多線程訪問成為線程安全却紧,來保證結(jié)果的準(zhǔn)確。如上面的代碼簡單加入@synchronized關(guān)鍵字胎撤。在保證結(jié)果準(zhǔn)確的同時晓殊,提高性能,才是優(yōu)秀的程序伤提。線程安全的優(yōu)先級高于性能巫俺。

好了,讓我們開始吧肿男。我準(zhǔn)備分成幾部分來總結(jié)涉及到多線程的內(nèi)容:

扎好馬步:線程的狀態(tài)

內(nèi)功心法:每個對象都有的方法

太祖長拳:基本線程類

九陰真經(jīng):高級多線程控制類

整理了一份Java核心知識點介汹。覆蓋了JVM、鎖舶沛、并發(fā)嘹承、Java反射、Spring原理如庭、微服務(wù)叹卷、Zookeeper、數(shù)據(jù)庫柱彻、數(shù)據(jù)結(jié)構(gòu)等大量知識點豪娜。基本上涵蓋了Java架構(gòu)所有的技術(shù)知識點的資料哟楷,還覆蓋了大廠面試題瘤载,同時也有一些springboot等項目源碼分享給大家

?

由于資料圖片太多就不一一的展示出來了 如果需要獲取 si我【666】獲取

?

扎好馬步:線程的狀態(tài)

?

各種狀態(tài)一目了然,值得一提的是"Blocked"和"Waiting"這兩個狀態(tài)的區(qū)別:

線程在Running的過程中可能會遇到阻塞(Blocked)情況

對Running狀態(tài)的線程加同步鎖(Synchronized)使其進(jìn)入(lock blocked pool ),同步鎖被釋放進(jìn)入可運行狀態(tài)(Runnable)卖擅。從jdk源碼注釋來看鸣奔,blocked指的是對monitor的等待(可以參考下文的圖)即該線程位于等待區(qū)墨技。

線程在Running的過程中可能會遇到等待(Waiting)情況

線程可以主動調(diào)用object.wait或者sleep,或者join(join內(nèi)部調(diào)用的是sleep挎狸,所以可看成sleep的一種)進(jìn)入扣汪。從jdk源碼注釋來看,waiting是等待另一個線程完成某一個操作锨匆,如join等待另一個完成執(zhí)行崭别,object.wait()等待object.notify()方法執(zhí)行。

Waiting狀態(tài)和Blocked狀態(tài)有點費解恐锣,我個人的理解是:Blocked其實也是一種wait茅主,等待的是monitor,但是和Waiting狀態(tài)不一樣土榴,舉個例子诀姚,有三個線程進(jìn)入了同步塊,其中兩個調(diào)用了object.wait()玷禽,進(jìn)入了waiting狀態(tài)赫段,這時第三個調(diào)用了object.notifyAll(),這時候前兩個線程就一個轉(zhuǎn)移到了Runnable,一個轉(zhuǎn)移到了Blocked矢赁。

從下文的monitor結(jié)構(gòu)圖來區(qū)別:每個 Monitor在某個時刻糯笙,只能被一個線程擁有,該線程就是 “Active Thread”坯台,而其它線程都是 “Waiting Thread”炬丸,分別在兩個隊列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的線程狀態(tài)Blocked,從jstack的dump中來看是 “Waiting for monitor entry”蜒蕾,而在 “Wait Set”中等待的線程狀態(tài)是Waiting,表現(xiàn)在jstack的dump中是 “in Object.wait()”焕阿。

此外咪啡,在runnable狀態(tài)的線程是處于被調(diào)度的線程,此時的調(diào)度順序是不一定的暮屡。Thread類中的yield方法可以讓一個running狀態(tài)的線程轉(zhuǎn)入runnable撤摸。

內(nèi)功心法:每個對象都有的方法

synchronized, wait, notify 是任何對象都具有的同步工具。讓我們先來了解他們

?

他們是應(yīng)用于同步問題的人工線程調(diào)度工具褒纲。講其本質(zhì)准夷,首先就要明確monitor的概念,Java中的每個對象都有一個監(jiān)視器莺掠,來監(jiān)測并發(fā)代碼的重入衫嵌。在非多線程編碼時該監(jiān)視器不發(fā)揮作用,反之如果在synchronized 范圍內(nèi)彻秆,監(jiān)視器發(fā)揮作用楔绞。

wait/notify必須存在于synchronized塊中结闸。并且,這三個關(guān)鍵字針對的是同一個監(jiān)視器(某對象的監(jiān)視器)酒朵。這意味著wait之后桦锄,其他線程可以進(jìn)入同步塊執(zhí)行。

當(dāng)某代碼并不持有監(jiān)視器的使用權(quán)時(如圖中5的狀態(tài)蔫耽,即脫離同步塊)去wait或notify结耀,會拋出java.lang.IllegalMonitorStateException。也包括在synchronized塊中去調(diào)用另一個對象的wait/notify匙铡,因為不同對象的監(jiān)視器不同桅锄,同樣會拋出此異常羔巢。

再講用法:

synchronized單獨使用:

代碼塊:如下,在多線程環(huán)境下,synchronized塊中的方法獲取了lock實例的monitor带迟,如果實例相同,那么只有一個線程能執(zhí)行該塊內(nèi)容

public class Thread1 implements Runnable {

? ? ? ?Object lock;

? ? ? ?public void run() { ?

? ? ? ? ? ?synchronized(lock){

? ? ? ? ? ? ?..do something

? ? ? ? ? ?}

? ? ? ?}

}

直接用于方法: 相當(dāng)于上面代碼中用lock來鎖定的效果苟呐,實際獲取的是Thread1類的monitor汪厨。更進(jìn)一步,如果修飾的是static方法蜂厅,則鎖定該類所有實例匪凡。

public class Thread1 implements Runnable {

? ? ? ?public synchronized void run() { ?

? ? ? ? ? ? ..do something

? ? ? ?}

}

synchronized, wait, notify結(jié)合:典型場景生產(chǎn)者消費者問題

/**

? ? * 生產(chǎn)者生產(chǎn)出來的產(chǎn)品交給店員

? ? */

? ?public synchronized void produce()

? ?{

? ? ? ?if(this.product >= MAX_PRODUCT)

? ? ? ?{

? ? ? ? ? ?try

? ? ? ? ? ?{

? ? ? ? ? ? ? ?wait(); ?

? ? ? ? ? ? ? ?System.out.println("產(chǎn)品已滿,請稍候再生產(chǎn)");

? ? ? ? ? ?}

? ? ? ? ? ?catch(InterruptedException e)

? ? ? ? ? ?{

? ? ? ? ? ? ? ?e.printStackTrace();

? ? ? ? ? ?}

? ? ? ? ? ?return;

? ? ? ?}

? ? ? ?this.product++;

? ? ? ?System.out.println("生產(chǎn)者生產(chǎn)第" + this.product + "個產(chǎn)品.");

? ? ? ?notifyAll(); ? //通知等待區(qū)的消費者可以取出產(chǎn)品了

? ?}

? ?/**

? ? * 消費者從店員取產(chǎn)品

? ? */

? ?public synchronized void consume()

? ?{

? ? ? ?if(this.product <= MIN_PRODUCT)

? ? ? ?{

? ? ? ? ? ?try

? ? ? ? ? ?{

? ? ? ? ? ? ? ?wait();

? ? ? ? ? ? ? ?System.out.println("缺貨,稍候再取");

? ? ? ? ? ?}

? ? ? ? ? ?catch (InterruptedException e)

? ? ? ? ? ?{

? ? ? ? ? ? ? ?e.printStackTrace();

? ? ? ? ? ?}

? ? ? ? ? ?return;

? ? ? ?}

? ? ? ?System.out.println("消費者取走了第" + this.product + "個產(chǎn)品.");

? ? ? ?this.product--;

? ? ? ?notifyAll(); ? //通知等待去的生產(chǎn)者可以生產(chǎn)產(chǎn)品了

? ?}

volatile

多線程的內(nèi)存模型:main memory(主存)、working memory(線程棧)掘猿,在處理數(shù)據(jù)時病游,線程會把值從主存load到本地棧,完成操作后再save回去(volatile關(guān)鍵詞的作用:每次針對該變量的操作都激發(fā)一次load and save)稠通。

?

針對多線程使用的變量如果不是volatile或者final修飾的衬衬,很有可能產(chǎn)生不可預(yù)知的結(jié)果(另一個線程修改了這個值,但是之后在某線程看到的是修改之前的值)改橘。其實道理上講同一實例的同一屬性本身只有一個副本滋尉。但是多線程是會緩存值的,本質(zhì)上飞主,volatile就是不去緩存狮惜,直接取值。在線程安全的情況下加volatile會犧牲性能碌识。

太祖長拳:基本線程類

基本線程類指的是Thread類碾篡,Runnable接口,Callable接口

Thread 類實現(xiàn)了Runnable接口筏餐,啟動一個線程的方法:

  MyThread my = new MyThread();

  my.start();

Thread類相關(guān)方法:

//當(dāng)前線程可轉(zhuǎn)讓cpu控制權(quán)开泽,讓別的就緒狀態(tài)線程運行(切換)

public static Thread.yield()

//暫停一段時間

public static Thread.sleep() ?

//在一個線程中調(diào)用other.join(),將等待other執(zhí)行完后才繼續(xù)本線程。

public join()

//后兩個函數(shù)皆可以被打斷

public interrupte()

關(guān)于中斷:它并不像stop方法那樣會中斷一個正在運行的線程胖烛。線程會不時地檢測中斷標(biāo)識位眼姐,以判斷線程是否應(yīng)該被中斷(中斷標(biāo)識值是否為true)诅迷。終端只會影響到wait狀態(tài)、sleep狀態(tài)和join狀態(tài)众旗。被打斷的線程會拋出InterruptedException罢杉。

Thread.interrupted()檢查當(dāng)前線程是否發(fā)生中斷,返回boolean

synchronized在獲鎖的過程中是不能被中斷的贡歧。

中斷是一個狀態(tài)滩租!interrupt()方法只是將這個狀態(tài)置為true而已。所以說正常運行的程序不去檢測狀態(tài)利朵,就不會終止律想,而wait等阻塞方法會去檢查并拋出異常。如果在正常運行的程序中添加while(!Thread.interrupted()) 绍弟,則同樣可以在中斷后離開代碼體

Thread類最佳實踐:

寫的時候最好要設(shè)置線程名稱 Thread.name技即,并設(shè)置線程組 ThreadGroup,目的是方便管理樟遣。在出現(xiàn)問題的時候而叼,打印線程棧 (jstack -pid) 一眼就可以看出是哪個線程出的問題,這個線程是干什么的豹悬。

如何獲取線程中的異常

?

Runnable

與Thread類似

Callable

future模式:并發(fā)模式的一種葵陵,可以有兩種形式,即無阻塞和阻塞瞻佛,分別是isDone和get脱篙。其中Future對象用來存放該線程的返回值以及狀態(tài)

ExecutorService e = Executors.newFixedThreadPool(3);

//submit方法有多重參數(shù)版本,及支持callable也能夠支持runnable接口類型.

Future future = e.submit(new myCallable());

future.isDone() //return true,false 無阻塞

future.get() // return 返回值伤柄,阻塞直到該線程運行結(jié)束

九陰真經(jīng):高級多線程控制類

以上都屬于內(nèi)功心法绊困,接下來是實際項目中常用到的工具了,Java1.5提供了一個非常高效實用的多線程包:java.util.concurrent, 提供了大量高級工具,可以幫助開發(fā)者編寫高效适刀、易維護(hù)考抄、結(jié)構(gòu)清晰的Java多線程程序。

1.ThreadLocal類

用處:保存線程的獨立變量蔗彤。對一個線程類(繼承自Thread)

當(dāng)使用ThreadLocal維護(hù)變量時,ThreadLocal為每個使用該變量的線程提供獨立的變量副本疯兼,所以每一個線程都可以獨立地改變自己的副本然遏,而不會影響其它線程所對應(yīng)的副本。常用于用戶登錄控制吧彪,如記錄session信息待侵。

實現(xiàn):每個Thread都持有一個TreadLocalMap類型的變量(該類是一個輕量級的Map,功能與map一樣姨裸,區(qū)別是桶里放的是entry而不是entry的鏈表秧倾。功能還是一個map怨酝。)以本身為key,以目標(biāo)為value那先。

主要方法是get()和set(T a)农猬,set之后在map里維護(hù)一個threadLocal -> a,get時將a返回售淡。ThreadLocal是一個特殊的容器斤葱。

2.原子類(AtomicInteger、AtomicBoolean……)

如果使用atomic wrapper class如atomicInteger揖闸,或者使用自己保證原子的操作揍堕,則等同于synchronized

//返回值為boolean

AtomicInteger.compareAndSet(int expect,int update)

該方法可用于實現(xiàn)樂觀鎖,考慮文中最初提到的如下場景:a給b付款10元汤纸,a扣了10元衩茸,b要加10元。此時c給b2元贮泞,但是b的加十元代碼約為:

if(b.value.compareAndSet(old, value)){

? return ;

}else{

? //try again

? // if that fails, rollback and log

}

AtomicReference

對于AtomicReference?來講楞慈,也許對象會出現(xiàn),屬性丟失的情況隙畜,即oldObject == current抖部,但是oldObject.getPropertyA != current.getPropertyA。

這時候议惰,AtomicStampedReference就派上用場了慎颗。這也是一個很常用的思路,即加上版本號

3.Lock類

lock: 在java.util.concurrent包內(nèi)言询。共有三個實現(xiàn):

ReentrantLock

ReentrantReadWriteLock.ReadLock

ReentrantReadWriteLock.WriteLock

主要目的是和synchronized一樣俯萎, 兩者都是為了解決同步問題,處理資源爭端而產(chǎn)生的技術(shù)运杭。功能類似但有一些區(qū)別夫啊。

區(qū)別如下:

lock更靈活,可以自由定義多把鎖的枷鎖解鎖順序(synchronized要按照先加的后解順序)

提供多種加鎖方案辆憔,lock 阻塞式, trylock 無阻塞式, lockInterruptily 可打斷式撇眯, 還有trylock的帶超時時間版本。

本質(zhì)上和監(jiān)視器鎖(即synchronized是一樣的)

能力越大虱咧,責(zé)任越大熊榛,必須控制好加鎖和解鎖,否則會導(dǎo)致災(zāi)難腕巡。

和Condition類的結(jié)合玄坦。

性能更高,對比如下圖:

?

ReentrantLock

可重入的意義在于持有鎖的線程可以繼續(xù)持有,并且要釋放對等的次數(shù)后才真正釋放該鎖煎楣。

使用方法是:

1.先new一個實例

static ReentrantLock r=new ReentrantLock();

2.加鎖

r.lock()或r.lockInterruptibly();

此處也是個不同豺总,后者可被打斷。當(dāng)a線程lock后择懂,b線程阻塞喻喳,此時如果是lockInterruptibly,那么在調(diào)用b.interrupt()之后休蟹,b線程退出阻塞沸枯,并放棄對資源的爭搶,進(jìn)入catch塊赂弓。(如果使用后者绑榴,必須throw interruptable exception 或catch)

3.釋放鎖

r.unlock()

必須做!何為必須做呢盈魁,要放在finally里面翔怎。以防止異常跳出了正常流程,導(dǎo)致災(zāi)難杨耙。這里補充一個小知識點赤套,finally是可以信任的:經(jīng)過測試,哪怕是發(fā)生了OutofMemoryError珊膜,finally塊中的語句執(zhí)行也能夠得到保證容握。

ReentrantReadWriteLock

可重入讀寫鎖(讀寫鎖的一個實現(xiàn))

  ReentrantReadWriteLock lock = new ReentrantReadWriteLock()

  ReadLock r = lock.readLock();

  WriteLock w = lock.writeLock();

兩者都有l(wèi)ock,unlock方法。寫寫车柠,寫讀互斥剔氏;讀讀不互斥≈竦唬可以實現(xiàn)并發(fā)讀的高效線程安全代碼

4.容器類

這里就討論比較常用的兩個:

BlockingQueue

ConcurrentHashMap

BlockingQueue

阻塞隊列谈跛。該類是java.util.concurrent包下的重要類,通過對Queue的學(xué)習(xí)可以得知塑陵,這個queue是單向隊列感憾,可以在隊列頭添加元素和在隊尾刪除或取出元素。類似于一個管  道令花,特別適用于先進(jìn)先出策略的一些應(yīng)用場景阻桅。普通的queue接口主要實現(xiàn)有PriorityQueue(優(yōu)先隊列),有興趣可以研究

BlockingQueue在隊列的基礎(chǔ)上添加了多線程協(xié)作的功能:

除了傳統(tǒng)的queue功能(表格左邊的兩列)之外兼都,還提供了阻塞接口put和take鳍刷,帶超時功能的阻塞接口offer和poll。put會在隊列滿的時候阻塞俯抖,直到有空間時被喚醒;take在隊 列空的時候阻塞瓦胎,直到有東西拿的時候才被喚醒芬萍。用于生產(chǎn)者-消費者模型尤其好用尤揣,堪稱神器。

常見的阻塞隊列有:

ArrayListBlockingQueue

LinkedListBlockingQueue

DelayQueue

SynchronousQueue

ConcurrentHashMap

高效的線程安全哈希map柬祠。請對比hashTable , concurrentHashMap, HashMap

5.管理類

管理類的概念比較泛北戏,用于管理線程,本身不是多線程的漫蛔,但提供了一些機制來利用上述的工具做一些封裝嗜愈。

了解到的值得一提的管理類:ThreadPoolExecutor和 JMX框架下的系統(tǒng)級管理類 ThreadMXBean

ThreadPoolExecutor

如果不了解這個類,應(yīng)該了解前面提到的ExecutorService莽龟,開一個自己的線程池非常方便:

ExecutorService e = Executors.newCachedThreadPool();

? ?ExecutorService e = Executors.newSingleThreadExecutor();

? ?ExecutorService e = Executors.newFixedThreadPool(3);

? ?// 第一種是可變大小線程池蠕嫁,按照任務(wù)數(shù)來分配線程,

? ?// 第二種是單線程池毯盈,相當(dāng)于FixedThreadPool(1)

? ?// 第三種是固定大小線程池。

? ?// 然后運行

? ?e.execute(new MyRunnableImpl());

該類內(nèi)部是通過ThreadPoolExecutor實現(xiàn)的搂赋,掌握該類有助于理解線程池的管理赘阀,本質(zhì)上,他們都是ThreadPoolExecutor類的各種實現(xiàn)版本脑奠。

corePoolSize:池內(nèi)線程初始值與最小值基公,就算是空閑狀態(tài),也會保持該數(shù)量線程宋欺。

maximumPoolSize:線程最大值轰豆,線程的增長始終不會超過該值。

keepAliveTime:當(dāng)池內(nèi)線程數(shù)高于corePoolSize時迄靠,經(jīng)過多少時間多余的空閑線程才會被回收秒咨。回收前處于wait狀態(tài)

unit:時間單位掌挚,可以使用TimeUnit的實例雨席,如TimeUnit.MILLISECONDS

workQueue:待入任務(wù)(Runnable)的等待場所,該參數(shù)主要影響調(diào)度策略吠式,如公平與否陡厘,是否產(chǎn)生餓死(starving)

threadFactory:線程工廠類,有默認(rèn)實現(xiàn)特占,如果有自定義的需要則需要自己實現(xiàn)ThreadFactory接口并作為參數(shù)傳入糙置。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市是目,隨后出現(xiàn)的幾起案子谤饭,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揉抵,死亡現(xiàn)場離奇詭異亡容,居然都是意外死亡,警方通過查閱死者的電腦和手機冤今,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門闺兢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人戏罢,你說我怎么就攤上這事屋谭。” “怎么了龟糕?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵桐磁,是天一觀的道長。 經(jīng)常有香客問我翩蘸,道長所意,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任催首,我火速辦了婚禮扶踊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘郎任。我一直安慰自己秧耗,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布舶治。 她就那樣靜靜地躺著分井,像睡著了一般。 火紅的嫁衣襯著肌膚如雪霉猛。 梳的紋絲不亂的頭發(fā)上尺锚,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天,我揣著相機與錄音惜浅,去河邊找鬼瘫辩。 笑死,一個胖子當(dāng)著我的面吹牛坛悉,可吹牛的內(nèi)容都是我干的伐厌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼裸影,長吁一口氣:“原來是場噩夢啊……” “哼挣轨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起轩猩,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤卷扮,失蹤者是張志新(化名)和其女友劉穎荡澎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體画饥,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡衔瓮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了抖甘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡葫慎,死狀恐怖衔彻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情偷办,我是刑警寧澤艰额,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站椒涯,受9級特大地震影響柄沮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜废岂,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一祖搓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧湖苞,春花似錦拯欧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至隆箩,卻和暖如春该贾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捌臊。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工杨蛋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人娃属。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓六荒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親矾端。 傳聞我的和親對象是個殘疾皇子掏击,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355