線程池

一、線程池簡(jiǎn)介

在實(shí)際開發(fā)中憾朴,如果每個(gè)請(qǐng)求到達(dá)就創(chuàng)建一個(gè)新線程狸捕,開銷是相當(dāng)大的。服務(wù)器在創(chuàng)建和銷毀線程上花費(fèi)的時(shí)間和消耗的系統(tǒng)資源都相當(dāng)大众雷,甚至可能要比在處理實(shí)際的用請(qǐng)求的時(shí)間和資源要多的多灸拍。除了創(chuàng)建和銷毀線程的開銷之外,活動(dòng)的線程也需要消耗系統(tǒng)資源砾省。如果在一個(gè)jvm里創(chuàng)建太多的線程鸡岗,可能會(huì)使系統(tǒng)由于過(guò)度消耗內(nèi)存或“切換過(guò)度”而導(dǎo)致系統(tǒng)資源不足。這就引入了線程池概念编兄。
??線程池的核心思想就是:連接復(fù)用轩性,通過(guò)建立一個(gè)數(shù)據(jù)庫(kù)連接池以及一套連接使用、分配狠鸳、管理策略揣苏,使得該線程池中的連接可以得到高效悯嗓、安全的復(fù)用,避免了數(shù)據(jù)庫(kù)連接頻繁建立卸察、關(guān)閉的開銷绅作。
??在線程池中,它自己維護(hù)一些數(shù)據(jù)連接蛾派,需要使用的時(shí)候直接使用其中一個(gè)連接俄认,用完之后不是關(guān)閉而是將它歸還,等待其他操作洪乍。

二眯杏、線程池的實(shí)現(xiàn)

2.1 線程池實(shí)現(xiàn)簡(jiǎn)介
??在Java1.5中提供了一個(gè)非常高效實(shí)用的多線程包:java.util.concurrent,提供了大量高級(jí)工具,可以幫助開發(fā)者編寫高效易維護(hù)壳澳、結(jié)構(gòu)清晰的Java多線程程序岂贩。這個(gè)是JDK自帶實(shí)現(xiàn)線程池的包。
??Java里面線程池的頂級(jí)接口是Executor巷波,但是嚴(yán)格意義上講Executor并不是一個(gè)線程池萎津,而只是一個(gè)執(zhí)行線程的工具。真正的線程池接口是ExecutorService抹镊。比較重要的幾個(gè)類:

類名 接口
ExecutorService 真正的線程池接口锉屈。
ScheduledExecutorService 能和Timer/TimerTask類似,解決那些需要任務(wù)重復(fù)執(zhí)行的問(wèn)題垮耳。
ThreadPoolExecutor ExecutorService的默認(rèn)實(shí)現(xiàn)(底層實(shí)現(xiàn))颈渊。
ScheduledThreadPoolExecutor 繼承ThreadPoolExecutor的ScheduledExecutorService接口實(shí)現(xiàn),周期性任務(wù)調(diào)度的類實(shí)現(xiàn)终佛。

一個(gè)線程池包括以下四個(gè)基本組成部分:
1俊嗽、線程池管理器(ThreadPool):用于創(chuàng)建并管理線程池,包括創(chuàng)建線程池铃彰,銷毀線程池绍豁,添加新任務(wù);
2牙捉、工作線程(PoolWorker):線程池中線程竹揍,在沒(méi)有任務(wù)時(shí)處于等待狀態(tài),可以循環(huán)的執(zhí)行任務(wù)鹃共;
3鬼佣、任務(wù)接口(Task):每個(gè)任務(wù)必須實(shí)現(xiàn)的接口,以供工作線程調(diào)度任務(wù)的執(zhí)行霜浴,它主要規(guī)定了任務(wù)的入口晶衷,任務(wù)執(zhí)行完后的收尾工作,任務(wù)的執(zhí)行狀態(tài)等;
4晌纫、任務(wù)隊(duì)列(taskQueue):用于存放沒(méi)有處理的任務(wù)税迷。提供一種緩沖機(jī)制。

要配置一個(gè)線程池是比較復(fù)雜的锹漱,尤其是對(duì)于線程池的原理不是很清楚的情況下箭养,很有可能配置的線程池不是較優(yōu)的,因此在Executors類里面提供了一些靜態(tài)工廠哥牍,生成一些常用的線程池:
1.創(chuàng)建一個(gè)單線程的線程池毕泌。這個(gè)線程池只有一個(gè)線程在工作,也就是相當(dāng)于單線程串行執(zhí)行所有任務(wù)嗅辣。如果這個(gè)唯一的線程因?yàn)楫惓=Y(jié)束撼泛,那么會(huì)有一個(gè)新的線程來(lái)替代它。此線程池保證所有任務(wù)的執(zhí)行順序按照任務(wù)的提交順序執(zhí)行澡谭。

ExecutorService executorService1 = Executors.newSingleThreadExecutor();

2.創(chuàng)建固定大小的線程池愿题。每次提交一個(gè)任務(wù)就創(chuàng)建一個(gè)線程,直到線程達(dá)到線程池的最大大小蛙奖。線程池的大小一旦達(dá)到最大值就會(huì)保持不變潘酗,如果某個(gè)線程因?yàn)閳?zhí)行異常而結(jié)束,那么線程池會(huì)補(bǔ)充一個(gè)新線程雁仲。

ExecutorService executorService2 = Executors.newFixedThreadPool(10);

3.調(diào)度型線程池,調(diào)度型線程池會(huì)根據(jù)Scheduled(任務(wù)列表)進(jìn)行延遲執(zhí)行仔夺,或者是進(jìn)行周期性的執(zhí)行.適用于一些周期性的工作。

ExecutorService executorService3 = Executors.newScheduledThreadPool(10);

4.創(chuàng)建一個(gè)可緩存的線程池伯顶。如果線程池的大小超過(guò)了處理任務(wù)所需要的線程囚灼,那么就會(huì)回收部分空閑(60秒不執(zhí)行任務(wù))的線程骆膝,當(dāng)任務(wù)數(shù)增加時(shí)祭衩,此線程池又可以智能的添加新線程來(lái)處理任務(wù)。此線程池不會(huì)對(duì)線程池大小做限制阅签,線程池大小完全依賴于操作系統(tǒng)(或者說(shuō)JVM)能夠創(chuàng)建的最大線程大小掐暮。

ExecutorService executorService4 = Executors.newCacheThreadPool();

2.2 簡(jiǎn)單的代碼示例
Executor.java

public class Executor {
  public static void main(String[] args) {
    //定義了線程池中最大存在的線程數(shù)目
    ExecutorService executorService=Executors.newFixedThreadPool(10);
    //添加一個(gè)新的任務(wù)
    for (int i = 0; i < 10; i++){
        executorService.execute(new Begincode());
    }
    executor.shutdown();
  }
}

Begincode.java

//無(wú)返回值的任務(wù)就是一個(gè)實(shí)現(xiàn)了runnable接口的類.使用run方法
public class Begincode implements Runnable { 
  public void run() { 
    System.out.println(“Begincode--runable”); 
  } 
}

//有返回值的任務(wù)是一個(gè)實(shí)現(xiàn)了callable接口的類.使用call方法
public class Begincode implements callable{ 
  public void call() { 
    System.out.println(“Begincode--callable”); 
  } 
}

代碼說(shuō)明:
1.ExecutorService接口對(duì)象來(lái)執(zhí)行任務(wù),該對(duì)象有兩個(gè)方法可以執(zhí)行任務(wù)execute和submit政钟。

  • execute這種方式提交沒(méi)有返回值路克,也就不能判斷是否執(zhí)行成功。
  • submit這種方式它會(huì)返回一個(gè)Future對(duì)象养交。通過(guò)future的get方法來(lái)獲取返回值精算,get方法會(huì)阻塞住直到任務(wù)完成。

2.當(dāng)我們不需要使用線程池的時(shí)候碎连,我們需要對(duì)其進(jìn)行關(guān)閉灰羽。有兩種方法可以關(guān)閉掉線程池。

  • shutdown():并不是直接關(guān)閉線程池,而是不再接受新的任務(wù)廉嚼。如果線程池內(nèi)有任務(wù)玫镐,那么把這些任務(wù)執(zhí)行完畢后,關(guān)閉線程池怠噪。
  • shutdownNow():這個(gè)方法表示不再接受新的任務(wù)恐似,并把任務(wù)隊(duì)列中的任務(wù)直接移出掉,如果有正在執(zhí)行的傍念,嘗試進(jìn)行停止矫夷。

2.3 阻塞隊(duì)列
??JDK使用了實(shí)現(xiàn)接口BlockingQueue的阻塞隊(duì)列來(lái)存儲(chǔ)待處理工作job,并把隊(duì)列作為構(gòu)造函數(shù)參數(shù)憋槐,從而實(shí)現(xiàn)業(yè)務(wù)可以靈活的擴(kuò)展定制線程池的隊(duì)列口四。業(yè)務(wù)也可使用JDK自身同步阻塞隊(duì)列SynchronousQueue、有界隊(duì)列ArrayBlockingQueue秦陋、無(wú)界隊(duì)列LinkedBlockingQueue蔓彩。

  • SynchronousQueue是無(wú)界的,也就是說(shuō)他存數(shù)任務(wù)的能力是沒(méi)有限制的驳概,但是由于該Queue本身的特性赤嚼,在某次添加元素后必須等待其他線程取走后才能繼續(xù)添加。如果運(yùn)行的線程等于或多于 corePoolSize顺又,則 Executor始終首選將請(qǐng)求加入隊(duì)列更卒,而不添加新的線程;如果無(wú)法將請(qǐng)求加入隊(duì)列稚照,則創(chuàng)建新的線程蹂空,除非創(chuàng)建此線程超出maximumPoolSize,在這種情況下果录,任務(wù)將被拒絕上枕。
  • LinkedBlockingQueue創(chuàng)建的線程就不會(huì)超過(guò) corePoolSize。如果運(yùn)行的線程少于 corePoolSize弱恒,則 Executor 始終首選添加新的線程辨萍,而不進(jìn)行排隊(duì)。如果運(yùn)行的線程等于或多于 corePoolSize返弹,則 Executor 始終首選將請(qǐng)求加入隊(duì)列锈玉,而不添加新的線程。換句說(shuō)义起,永遠(yuǎn)也不會(huì)觸發(fā)產(chǎn)生新的線程拉背!corePoolSize大小的線程數(shù)會(huì)一直運(yùn)行,忙完當(dāng)前的默终,就從隊(duì)列中拿任務(wù)開始運(yùn)行椅棺。所以要防止任務(wù)瘋長(zhǎng)抡诞,比如任務(wù)運(yùn)行的實(shí)行比較長(zhǎng),而添加任務(wù)的速度遠(yuǎn)遠(yuǎn)超過(guò)處理任務(wù)的時(shí)間土陪,而且還不斷增加昼汗,不一會(huì)兒就爆了。
  • ArrayBlockingQueue這個(gè)是最為復(fù)雜的使用鬼雀,所以JDK不推薦使用也有些道理顷窒。與上面的相比,最大的特點(diǎn)便是可以防止資源耗盡的情況發(fā)生源哩。

三鞋吉、線程池帶來(lái)的好處

  • 降低資源消耗。通過(guò)重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建和銷毀造成的消耗励烦;
  • 提高響應(yīng)速度谓着。當(dāng)任務(wù)到達(dá)時(shí),任務(wù)可以不需要等到線程創(chuàng)建就能立即執(zhí)行坛掠;
  • 提高線程的可管理性赊锚。線程是稀缺資源,如果無(wú)限制的創(chuàng)建屉栓,不僅會(huì)消耗系統(tǒng)資源舷蒲,還會(huì)降低系統(tǒng)的穩(wěn)定性,使用線程池可以進(jìn)行統(tǒng)一的分配友多,調(diào)優(yōu)和監(jiān)控牲平。
  • 線程池可以應(yīng)對(duì)突然大爆發(fā)量的訪問(wèn),通過(guò)有限個(gè)固定線程為大量的操作服務(wù)域滥,減少創(chuàng)建和銷毀線程所需的時(shí)間纵柿。

四、使用線程池的風(fēng)險(xiǎn)

雖然線程池是構(gòu)建多線程應(yīng)用程序的強(qiáng)大機(jī)制启绰,但使用它并不是沒(méi)有風(fēng)險(xiǎn)的昂儒。用線程池構(gòu)建的應(yīng)用程序容易遭受任何其它多線程應(yīng)用程序容易遭受的所有并發(fā)風(fēng)險(xiǎn),諸如同步錯(cuò)誤和死鎖酬土,它還容易遭受特定于線程池的少數(shù)其它風(fēng)險(xiǎn)荆忍,諸如與池有關(guān)的死鎖、資源不足和線程泄漏撤缴。

死鎖
??雖然任何多線程程序中都有死鎖的風(fēng)險(xiǎn),但線程池卻引入了另一種死鎖可能叽唱。這可能會(huì)導(dǎo)致死鎖屈呕,在那種死鎖中,所有線程都被一些任務(wù)所占用棺亭,而這些線程又在排隊(duì)虎眨,同步等待其他任務(wù)結(jié)果,而這些任務(wù)又無(wú)法執(zhí)行,因?yàn)樗械木€程都很忙嗽桩。

資源不足
??線程消耗包括內(nèi)存和其它系統(tǒng)資源在內(nèi)的大量資源岳守。雖然線程之間切換的調(diào)度開銷很小,但如果有很多線程碌冶,環(huán)境切換也可能嚴(yán)重地影響程序的性能湿痢。
??線程池大小決定了在指定時(shí)間內(nèi)能夠處理的并發(fā)請(qǐng)求數(shù)。如果線程池太大扑庞,那么被那些線程消耗的資源可能嚴(yán)重地影響系統(tǒng)性能譬重。在線程之間進(jìn)行切換將會(huì)浪費(fèi)時(shí)間譬猫,而且使用超出比您實(shí)際需要的線程可能會(huì)引起資源匱乏問(wèn)題伐蒋,因?yàn)槌刂芯€程正在消耗一些資源壮不,而這些資源可能會(huì)被其它任務(wù)更有效地利用乘碑。
??除了線程自身所使用的資源以外痢毒,服務(wù)請(qǐng)求時(shí)所做的工作可能需要其它資源渣聚,例如 JDBC 連接阳惹、套接字或文件的榛。這些也都是有限資源租悄,有太多的并發(fā)請(qǐng)求也可能引起失效邑遏。如果一個(gè) web 應(yīng)用接收到的請(qǐng)求數(shù)高于線程池大小,多出來(lái)的請(qǐng)求將進(jìn)入隊(duì)列等待恰矩,或被拒絕记盒。

并發(fā)錯(cuò)誤
??線程池和其它排隊(duì)機(jī)制依靠使用 wait() 和 notify() 方法,這兩個(gè)方法都難于使用外傅。如果編碼不正確纪吮,那么可能丟失通知,導(dǎo)致線程保持空閑狀態(tài)萎胰,盡管隊(duì)列中有工作要處理碾盟。使用這些方法時(shí),必須格外小心技竟;即便是專家也可能在它們上面出錯(cuò)冰肴。而最好使用現(xiàn)有的、已經(jīng)知道能工作的實(shí)現(xiàn)榔组,例如使用無(wú)須編寫您自己的池中討論的util.concurrent 包熙尉。

線程泄露
??各種類型的線程池中一個(gè)嚴(yán)重的風(fēng)險(xiǎn)是線程泄漏,當(dāng)從池中除去一個(gè)線程以執(zhí)行一項(xiàng)任務(wù)搓扯,而在任務(wù)完成后該線程卻沒(méi)有返回池時(shí)检痰,會(huì)發(fā)生這種情況。發(fā)生線程泄漏的一種情形出現(xiàn)在任務(wù)拋出一個(gè) RuntimeException 或一個(gè) Error 時(shí)锨推。如果池類沒(méi)有捕捉到它們铅歼,那么線程只會(huì)退出而線程池的大小將會(huì)永久減少一個(gè)公壤。當(dāng)這種情況發(fā)生的次數(shù)足夠多時(shí),線程池最終就為空椎椰,而且系統(tǒng)將停止厦幅,因?yàn)闆](méi)有可用的線程來(lái)處理任務(wù)。
??有些任務(wù)可能會(huì)永遠(yuǎn)等待某些資源或來(lái)自用戶的輸入慨飘,而這些資源又不能保證變得可用确憨,用戶可能也已經(jīng)回家了,諸如此類的任務(wù)會(huì)永久停止套媚,而這些停止的任務(wù)也會(huì)引起和線程泄漏同樣的問(wèn)題缚态。如果某個(gè)線程被這樣一個(gè)任務(wù)永久地消耗著,那么它實(shí)際上就被從池除去了堤瘤。對(duì)于這樣的任務(wù)玫芦,應(yīng)該要么只給予它們自己的線程,要么只讓它們等待有限的時(shí)間本辐。

五桥帆、使用線程池的準(zhǔn)則

①不要把那些同步等待其它任務(wù)結(jié)果的任務(wù)線程加入隊(duì)列排隊(duì),因?yàn)榭赡芤l(fā)死鎖慎皱。

②在為時(shí)間可能很長(zhǎng)的操作使用合用的線程時(shí)要小心老虫。如果程序必須等待諸如 I/O 完成這樣的某個(gè)資源,那么請(qǐng)指定最長(zhǎng)的等待時(shí)間茫多,以及隨后是失效還是將任務(wù)重新排隊(duì)以便稍后執(zhí)行祈匙。

③根據(jù)任務(wù)相應(yīng)地調(diào)整線程池大小
??要有效地調(diào)整線程池大小,您需要理解正在排隊(duì)的任務(wù)以及它們正在做什么天揖。它們是 CPU 限制的(CPU-bound)嗎夺欲?它們是 I/O 限制的(I/O-bound)嗎?您的答案將影響您如何調(diào)整應(yīng)用程序今膊。
??調(diào)整線程池的大小基本上就是避免兩類錯(cuò)誤:線程太少或線程太多些阅。幸運(yùn)的是,對(duì)于大多數(shù)應(yīng)用程序來(lái)說(shuō)斑唬,太多和太少之間的余地相當(dāng)寬市埋。
??一個(gè)系統(tǒng)最快的部分是CPU,所以決定一個(gè)系統(tǒng)吞吐量上限的是CPU恕刘。增強(qiáng)CPU處理能力缤谎,可以提高系統(tǒng)吞吐量上限。但根據(jù)短板效應(yīng)雪营,真實(shí)的系統(tǒng)吞吐量并不能單純根據(jù)CPU來(lái)計(jì)算弓千。那要提高系統(tǒng)吞吐量,就需要從“系統(tǒng)短板”(比如網(wǎng)絡(luò)延遲献起、IO)著手:

  • 盡量提高短板操作的并行化比率洋访,比如多線程下載技術(shù)
  • 增強(qiáng)短板能力,比如用NIO替代IO

CPU密集型應(yīng)用
??CPU密集則是大量CPU時(shí)間都用于進(jìn)行計(jì)算谴餐。需要進(jìn)行矩陣運(yùn)算視頻解碼這些操作的通常屬于CPU密集姻政。觀察CPU占用的話多數(shù)時(shí)間都是出于I/O wait狀態(tài)(圖中綠色或黃色)。

I/O密集型應(yīng)用
??一個(gè)I/O密集的應(yīng)用通常行為是反復(fù)去讀寫磁盤文件(圖中藍(lán)色)岂嗓。

通常汁展,線程等待時(shí)間所占比例越高,需要越多線程厌殉。線程CPU時(shí)間所占比例越高食绿,需要越少線程。
??一般說(shuō)來(lái)公罕,大家認(rèn)為線程池的大小經(jīng)驗(yàn)值應(yīng)該這樣設(shè)置:(其中N為CPU的個(gè)數(shù))

  • 如果是CPU密集型應(yīng)用器紧,則線程池大小設(shè)置為N+1
  • 如果是IO密集型應(yīng)用,則線程池大小設(shè)置為2N+1

如果一臺(tái)服務(wù)器上只部署這一個(gè)應(yīng)用并且只有這一個(gè)線程池楼眷,那么這種估算或許合理铲汪,具體還需自行測(cè)試驗(yàn)證。但是罐柳,IO優(yōu)化中掌腰,確定線程池的大小相對(duì)比較復(fù)雜,涉及到下游系統(tǒng)的響應(yīng)時(shí)間张吉,因?yàn)橐粋€(gè)線程常常因?yàn)榈却渌到y(tǒng)的響應(yīng)而被阻塞齿梁。所以我們必須增加線程的數(shù)量以更好地利用CPU,所以這樣的估算公式可能更適合:
??最佳線程數(shù)目 = (線程等待時(shí)間與線程CPU時(shí)間之比 + 1) CPU數(shù)目*

很顯然肮蛹,線程等待時(shí)間所占比例越高勺择,需要越多線程。線程CPU時(shí)間所占比例越高蔗崎,需要越少線程酵幕。

六、使用線程池就一定比使用單線程高效缓苛?

答案是否定的芳撒,比如Redis就是單線程的,但它卻非常高效未桥,基本操作都能達(dá)到十萬(wàn)量級(jí)/s笔刹。從線程這個(gè)角度來(lái)看,部分原因在于:多線程帶來(lái)線程上下文切換開銷冬耿,單線程就沒(méi)有這種開銷舌菜。
??當(dāng)然“Redis很快”更本質(zhì)的原因在于:Redis基本都是內(nèi)存操作,這種情況下單線程可以很高效地利用CPU亦镶。而多線程適用場(chǎng)景一般是:存在相當(dāng)比例的IO和網(wǎng)絡(luò)操作日月。

最后編輯于
?著作權(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ō)我怎么就攤上這事怪瓶。” “怎么了坛吁?”我有些...
    開封第一講書人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵劳殖,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我拨脉,道長(zhǎng)哆姻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任玫膀,我火速辦了婚禮矛缨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘帖旨。我一直安慰自己箕昭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開白布解阅。 她就那樣靜靜地躺著落竹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪货抄。 梳的紋絲不亂的頭發(fā)上述召,一...
    開封第一講書人閱讀 51,521評(píng)論 1 304
  • 那天,我揣著相機(jī)與錄音蟹地,去河邊找鬼积暖。 笑死,一個(gè)胖子當(dāng)著我的面吹牛怪与,可吹牛的內(nèi)容都是我干的夺刑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼遍愿!你這毒婦竟也來(lái)了存淫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤错览,失蹤者是張志新(化名)和其女友劉穎纫雁,沒(méi)想到半個(gè)月后煌往,有當(dāng)?shù)厝嗽跇淞掷锇l(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
  • 文/蒙蒙 一民傻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧场斑,春花似錦漓踢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至青责,卻和暖如春挺据,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爽柒。 一陣腳步聲響...
    開封第一講書人閱讀 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)容