原子操作 CAS
LongAdder
JDK1.8 時(shí)命爬,java.util.concurrent.atomic 包中提供了一個(gè)新的原子類:LongAdder吧黄。
根據(jù) Oracle 官方文檔的介紹,LongAdder 在高并發(fā)的場(chǎng)景下會(huì)比它的前輩———
—AtomicLong 具有更好的性能,代價(jià)是消耗更多的內(nèi)存空間渺蒿。
AtomicLong 是利用了底層的 CAS 操作來提供并發(fā)性的,調(diào)用了 Unsafe 類的
getAndAddLong 方法彪薛,該方法是個(gè) native 方法茂装,它的邏輯是采用自旋的方式不斷
更新目標(biāo)值,直到更新成功善延。
在并發(fā)量較低的環(huán)境下少态,線程沖突的概率比較小,自旋的次數(shù)不會(huì)很多挚冤。但
是况增,高并發(fā)環(huán)境下,N 個(gè)線程同時(shí)進(jìn)行自旋操作训挡,會(huì)出現(xiàn)大量失敗并不斷自旋的
情況澳骤,此時(shí) AtomicLong 的自旋會(huì)成為瓶頸。
這就是 LongAdder 引入的初衷——解決高并發(fā)環(huán)境下 AtomicLong 的自旋瓶
頸問題澜薄。
AtomicLong 中有個(gè)內(nèi)部變量 value 保存著實(shí)際的 long 值为肮,所有的操作都是
針對(duì)該變量進(jìn)行。也就是說肤京,高并發(fā)環(huán)境下颊艳,value 變量其實(shí)是一個(gè)熱點(diǎn),也就
是 N 個(gè)線程競(jìng)爭(zhēng)一個(gè)熱點(diǎn)忘分。
LongAdder 的基本思路就是分散熱點(diǎn)棋枕,將 value 值分散到一個(gè)數(shù)組中,不同
線程會(huì)命中到數(shù)組的不同槽中妒峦,各個(gè)線程只對(duì)自己槽中的那個(gè)值進(jìn)行 CAS 操作重斑,
這樣熱點(diǎn)就被分散了,沖突的概率就小很多肯骇。如果要獲取真正的 long 值窥浪,只要
將各個(gè)槽中的變量值累加返回。
這種做法和 ConcurrentHashMap 中的“分段鎖”其實(shí)就是類似的思路笛丙。
LongAdder 提供的 API 和 AtomicLong 比較接近漾脂,兩者都能以原子的方式對(duì)
long 型變量進(jìn)行增減。
但是 AtomicLong 提供的功能其實(shí)更豐富胚鸯,尤其是 addAndGet骨稿、
decrementAndGet、compareAndSet 這些方法。
addAndGet啊终、decrementAndGet 除了單純的做自增自減外镜豹,還可以立即獲取
增減后的值,而 LongAdder 則需要做同步控制才能精確獲取增減后的值蓝牲。如果業(yè)
務(wù)需求需要精確的控制計(jì)數(shù)趟脂,做計(jì)數(shù)比較,AtomicLong 也更合適例衍。
另外昔期,從空間方面考慮,LongAdder 其實(shí)是一種“空間換時(shí)間”的思想佛玄,從
這一點(diǎn)來講 AtomicLong 更適合硼一。
總之,低并發(fā)梦抢、一般的業(yè)務(wù)場(chǎng)景下 AtomicLong 是足夠了般贼。如果并發(fā)量很多,
存在大量寫多讀少的情況奥吩,那 LongAdder 可能更合適哼蛆。適合的才是最好的,如果
真出現(xiàn)了需要考慮到底用 AtomicLong 好還是 LongAdder 的業(yè)務(wù)場(chǎng)景霞赫,那么這樣
的討論是沒有意義的腮介,因?yàn)檫@種情況下要么進(jìn)行性能測(cè)試,以準(zhǔn)確評(píng)估在當(dāng)前業(yè)
務(wù)場(chǎng)景下兩者的性能端衰,要么換個(gè)思路尋求其它解決方案叠洗。
對(duì)于 LongAdder 來說,內(nèi)部有一個(gè) base 變量旅东,一個(gè) Cell[]數(shù)組灭抑。
base 變量:非競(jìng)態(tài)條件下,直接累加到該變量上抵代。
Cell[]數(shù)組:競(jìng)態(tài)條件下腾节,累加個(gè)各個(gè)線程自己的槽 Cell[i]中。
所以主守,最終結(jié)果的計(jì)算應(yīng)該是
在實(shí)際運(yùn)用的時(shí)候,只有從未出現(xiàn)過并發(fā)沖突的時(shí)候榄融,base 基數(shù)才會(huì)使用
到参淫,一旦出現(xiàn)了并發(fā)沖突,之后所有的操作都只針對(duì) Cell[]數(shù)組中的單元 Cell愧杯。
而 LongAdder 最終結(jié)果的求和涎才,并沒有使用全局鎖,返回值不是絕對(duì)準(zhǔn)確的,
因?yàn)檎{(diào)用這個(gè)方法時(shí)還有其他線程可能正在進(jìn)行計(jì)數(shù)累加耍铜,所以只能得到某個(gè)時(shí)
刻的近似值邑闺,這也就是 LongAdder 并不能完全替代 LongAtomic 的原因之一。
而且從測(cè)試情況來看棕兼,線程數(shù)越多陡舅,并發(fā)操作數(shù)越大,LongAdder 的優(yōu)勢(shì)越
大伴挚,線程數(shù)較小時(shí)靶衍,AtomicLong 的性能還超過了 LongAdder。 其他新增
除了新引入 LongAdder 外茎芋,還有引入了它的三個(gè)兄弟類:LongAccumulator颅眶、
DoubleAdder、DoubleAccumulator田弥。
LongAccumulator 是 LongAdder 的增強(qiáng)版涛酗。LongAdder 只能針對(duì)數(shù)值的進(jìn)行加
減運(yùn)算,而 LongAccumulator 提供了自定義的函數(shù)操作偷厦。
通過 LongBinaryOperator商叹,可以自定義對(duì)入?yún)⒌娜我獠僮鳎⒎祷亟Y(jié)果
(LongBinaryOperator 接收 2 個(gè) long 作為參數(shù)沪哺,并返回 1 個(gè) long)沈自。
LongAccumulator 內(nèi)部原理和 LongAdder 幾乎完全一樣。
DoubleAdder 和 DoubleAccumulator 用于操作 double 原始類型辜妓。
StampLock
StampedLock是Java8引入的一種新的所機(jī)制,簡(jiǎn)單的理解,可以認(rèn)為它是讀寫
鎖的一個(gè)改進(jìn)版本,讀寫鎖雖然分離了讀和寫的功能,使得讀與讀之間可以完全并
發(fā),但是讀和寫之間依然是沖突的,讀鎖會(huì)完全阻塞寫鎖,它使用的依然是悲觀的
鎖策略.如果有大量的讀線程,他也有可能引起寫線程的饑餓枯途。
而 StampedLock 則提供了一種樂觀的讀策略,這種樂觀策略的鎖非常類似于
無鎖的操作,使得樂觀鎖完全不會(huì)阻塞寫線程。
它的思想是讀寫鎖中讀不僅不阻塞讀籍滴,同時(shí)也不應(yīng)該阻塞寫酪夷。
讀不阻塞寫的實(shí)現(xiàn)思路:
在讀的時(shí)候如果發(fā)生了寫,則應(yīng)當(dāng)重讀而不是在讀的時(shí)候直接阻塞寫孽惰!即讀
寫之間不會(huì)阻塞對(duì)方晚岭,但是寫和寫之間還是阻塞的!
StampedLock 的內(nèi)部實(shí)現(xiàn)是基于 CLH 的勋功。
參考代碼坦报,參見 cn.enjoyedu.cha. StampedLockDemo
CompleteableFuture
Future 的不足
Future 是Java 5添加的類,用來描述一個(gè)異步計(jì)算的結(jié)果狂鞋。你可以使用 isDone
方法檢查計(jì)算是否完成片择,或者使用 get 阻塞住調(diào)用線程,直到計(jì)算完成返回結(jié)果骚揍,
你也可以使用 cancel 方法停止任務(wù)的執(zhí)行字管。
雖然 Future 以及相關(guān)使用方法提供了異步執(zhí)行任務(wù)的能力啰挪,但是對(duì)于結(jié)果
的獲取卻是很不方便,只能通過阻塞或者輪詢的方式得到任務(wù)的結(jié)果嘲叔。阻塞的方
式顯然和我們的異步編程的初衷相違背亡呵,輪詢的方式又會(huì)耗費(fèi)無謂的 CPU 資源,
而且也不能及時(shí)地得到計(jì)算結(jié)果硫戈,為什么不能用觀察者設(shè)計(jì)模式當(dāng)計(jì)算結(jié)果完成
及時(shí)通知監(jiān)聽者呢锰什?。
Java 的一些框架掏愁,比如 Netty歇由,自己擴(kuò)展了 Java 的 Future 接口,提供了
addListener 等多個(gè)擴(kuò)展方法果港,Google guava 也提供了通用的擴(kuò)展
Future:ListenableFuture沦泌、SettableFuture 以及輔助類 Futures 等,方便異步編程。
同時(shí) Future 接口很難直接表述多個(gè) Future 結(jié)果之間的依賴性辛掠。實(shí)際開發(fā)中谢谦,
我們經(jīng)常需要達(dá)成以下目的:
將兩個(gè)異步計(jì)算合并為一個(gè)——這兩個(gè)異步計(jì)算之間相互獨(dú)立,同時(shí)第二個(gè)
又依賴于第一個(gè)的結(jié)果萝衩。
等待 Future 集合中的所有任務(wù)都完成回挽。
僅等待 Future 集合中最快結(jié)束的任務(wù)完成(有可能因?yàn)樗鼈冊(cè)噲D通過不同
的方式計(jì)算同一個(gè)值),并返回它的結(jié)果猩谊。
應(yīng)對(duì) Future 的完成事件(即當(dāng) Future 的完成事件發(fā)生時(shí)會(huì)收到通知千劈,并
能使用 Future 計(jì)算的結(jié)果進(jìn)行下一步的操作,不只是簡(jiǎn)單地阻塞等待操作的結(jié)
果)
CompleteableFuture
JDK1.8 才新加入的一個(gè)實(shí)現(xiàn)類 CompletableFuture牌捷,實(shí)現(xiàn)了
Future<T>墙牌,CompletionStage<T>兩個(gè)接口。實(shí)現(xiàn)了 Future 接口暗甥,意味著可以像以
前一樣通過阻塞或者輪詢的方式獲得結(jié)果喜滨。
創(chuàng)建
除了直接 new 出一個(gè) CompletableFuture 的實(shí)例,還可以通過工廠方法創(chuàng)建
CompletableFuture 的實(shí)例
工廠方法:
Asynsc表示異步,而supplyAsync與runAsync 不同在與前者異步返回一個(gè)結(jié)果, 后者是 void.第二個(gè)函數(shù)第二個(gè)參數(shù)表示是用我們自己創(chuàng)建的線程池,否則采用默
認(rèn)的 ForkJoinPool.commonPool()作為它的線程池撤防。
獲得結(jié)果的方法
public T get()
public T get(long timeout, TimeUnit unit)
public T getNow(T valueIfAbsent)
public T join()
getNow 有點(diǎn)特殊虽风,如果結(jié)果已經(jīng)計(jì)算完則返回結(jié)果或者拋出異常,否則返
回給定的 valueIfAbsent 值寄月。
join 返回計(jì)算的結(jié)果或者拋出一個(gè) unchecked 異常(CompletionException)辜膝,它
和 get 對(duì)拋出的異常的處理有些細(xì)微的區(qū)別。
參見 cn.enjoyedu.cha.cfdemo 下 CFDemo 和 JoinAndGet
輔助方法
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
allOf 方法是當(dāng)所有的 CompletableFuture 都執(zhí)行完后執(zhí)行計(jì)算漾肮。
anyOf 方法是當(dāng)任意一個(gè) CompletableFuture 執(zhí)行完后就會(huì)執(zhí)行計(jì)算厂抖,計(jì)算的
結(jié)果相同。
參見 cn.enjoyedu.cha.cfdemo 下 AllofAnyOf
CompletionStage 是一個(gè)接口初橘,從命名上看得知是一個(gè)完成的階段验游,它代表
了一個(gè)特定的計(jì)算的階段,可以同步或者異步的被完成保檐。你可以把它看成一個(gè)計(jì)
算流水線上的一個(gè)單元耕蝉,并最終會(huì)產(chǎn)生一個(gè)最終結(jié)果,這意味著幾個(gè)
CompletionStage 可以串聯(lián)起來夜只,一個(gè)完成的階段可以觸發(fā)下一階段的執(zhí)行垒在,接
著觸發(fā)下一次,再接著觸發(fā)下一次扔亥,……….场躯。
總結(jié) CompletableFuture 幾個(gè)關(guān)鍵點(diǎn):
1、計(jì)算可以由 Future 旅挤,Consumer 或者 Runnable 接口中的 apply踢关,accept
或者 run 等方法表示。
2粘茄、計(jì)算的執(zhí)行主要有以下
a. 默認(rèn)執(zhí)行
b. 使用默認(rèn)的 CompletionStage 的異步執(zhí)行提供者異步執(zhí)行签舞。這些方法名使
用 someActionAsync 這種格式表示。
c. 使用 Executor 提供者異步執(zhí)行柒瓣。這些方法同樣也是 someActionAsync 這
種格式儒搭,但是會(huì)增加一個(gè) Executor 參數(shù)。
CompletableFuture 里大約有五十種方法芙贫,但是可以進(jìn)行歸類搂鲫,
變換類 thenApply:
關(guān)鍵入?yún)⑹呛瘮?shù)式接口 Function。它的入?yún)⑹巧弦粋€(gè)階段計(jì)算后的結(jié)果磺平,返
回值是經(jīng)過轉(zhuǎn)化后結(jié)果魂仍。
消費(fèi)類 thenAccept:
關(guān)鍵入?yún)⑹呛瘮?shù)式接口 Consumer。它的入?yún)⑹巧弦粋€(gè)階段計(jì)算后的結(jié)果褪秀,
沒有返回值蓄诽。
執(zhí)行操作類 thenRun:
對(duì)上一步的計(jì)算結(jié)果不關(guān)心,執(zhí)行下一個(gè)操作媒吗,入?yún)⑹且粋€(gè) Runnable 的實(shí)
例仑氛,表示上一步完成后執(zhí)行的操作。
結(jié)合轉(zhuǎn)化類:
需要上一步的處理返回值闸英,并且 other 代表的 CompletionStage 有返回值之
后锯岖,利用這兩個(gè)返回值,進(jìn)行轉(zhuǎn)換后返回指定類型的值甫何。
兩個(gè) CompletionStage 是并行執(zhí)行的出吹,它們之間并沒有先后依賴順序,other
并不會(huì)等待先前的 CompletableFuture 執(zhí)行完畢后再執(zhí)行辙喂。
結(jié)合轉(zhuǎn)化類
對(duì)于 Compose 可以連接兩個(gè) CompletableFuture捶牢,其內(nèi)部處理邏輯是當(dāng)?shù)谝?br>
個(gè) CompletableFuture 處理沒有完成時(shí)會(huì)合并成一個(gè) CompletableFuture,如果處理
完成鸠珠,第二個(gè) future 會(huì)緊接上一個(gè) CompletableFuture 進(jìn)行處理。
第一個(gè) CompletableFuture 的處理結(jié)果是第二個(gè) future 需要的輸入?yún)?shù)秋麸。
結(jié)合消費(fèi)類:
需要上一步的處理返回值渐排,并且 other 代表的 CompletionStage 有返回值之
后,利用這兩個(gè)返回值灸蟆,進(jìn)行消費(fèi)
運(yùn)行后執(zhí)行類:
不關(guān)心這兩個(gè) CompletionStage 的結(jié)果驯耻,只關(guān)心這兩個(gè) CompletionStage 都執(zhí)
行完畢,之后再進(jìn)行操作(Runnable)炒考。
取最快轉(zhuǎn)換類:
兩個(gè) CompletionStage可缚,誰計(jì)算的快,我就用那個(gè) CompletionStage 的結(jié)果進(jìn)
行下一步的轉(zhuǎn)化操作≌啵現(xiàn)實(shí)開發(fā)場(chǎng)景中帘靡,總會(huì)碰到有兩種渠道完成同一個(gè)事情,
所以就可以調(diào)用這個(gè)方法瓤帚,找一個(gè)最快的結(jié)果進(jìn)行處理测柠。
取最快消費(fèi)類:
兩個(gè) CompletionStage,誰計(jì)算的快缘滥,我就用那個(gè) CompletionStage 的結(jié)果進(jìn)
行下一步的消費(fèi)操作轰胁。
取最快運(yùn)行后執(zhí)行類:
兩個(gè) CompletionStage,任何一個(gè)完成了都會(huì)執(zhí)行下一步的操作(Runnable)朝扼。
異常補(bǔ)償類:
當(dāng)運(yùn)行時(shí)出現(xiàn)了異常赃阀,可以通過 exceptionally 進(jìn)行補(bǔ)償。
運(yùn)行后記錄結(jié)果類:
action 執(zhí)行完畢后它的結(jié)果返回原始的 CompletableFuture 的計(jì)算結(jié)果或者返回
異常擎颖。所以不會(huì)對(duì)結(jié)果產(chǎn)生任何的作用榛斯。
運(yùn)行后處理結(jié)果類:
運(yùn)行完成時(shí),對(duì)結(jié)果的處理搂捧。這里的完成時(shí)有兩種情況驮俗,一種是正常執(zhí)行,
返回值允跑。另外一種是遇到異常拋出造成程序的中斷王凑。 補(bǔ)充:Lambda 速成
本補(bǔ)充章節(jié)僅為沒接觸過 Lambda 的同學(xué)快速入門和速查,更具體的 Lamba
的知識(shí)請(qǐng)自行查閱相關(guān)書籍和博客聋丝。相關(guān)代碼放在 cn.enjoyedu.cha.lambda 下
現(xiàn)在我們有一個(gè)實(shí)體類索烹,我們會(huì)對(duì)這個(gè)實(shí)體類進(jìn)行操作。
第一步
我們想從一批 Circle 中挑選出挑選出半徑為 2 的圓弱睦,于是我們寫了一個(gè)方法
這樣百姓,無疑很不優(yōu)雅,如果我們想挑選半徑為 3 的圓况木,難道還要再寫一個(gè)方
法垒拢?于是我們考慮將選擇條件進(jìn)行參數(shù)化旬迹,比如根據(jù)顏色挑選出圓或者根據(jù)半徑
挑選出圓
但是,這種實(shí)現(xiàn)求类,還是有問題的舱权,1、選擇條件變化了仑嗅,那么相應(yīng)的方法也
要變,比如我們想挑選半徑大于 3 的圓张症,怎么辦仓技?如果我要根據(jù)多個(gè)條件選擇,
怎么辦俗他?難道把所有的條件都傳入嗎脖捻?于是,我們考慮定義一個(gè)挑選圓的接口兆衅,
程序進(jìn)化到了第二歩
第二步
進(jìn)行行為參數(shù)化地沮,定義一個(gè)接口
在進(jìn)行圓的挑選的方法里,我們把這個(gè)接口作為參數(shù)進(jìn)行傳遞
然后羡亩,我們只要按業(yè)務(wù)需求實(shí)現(xiàn)接口摩疑,并傳入實(shí)現(xiàn)類的實(shí)例即可
這種方式可以提高靈活性,但是業(yè)務(wù)上每增加一個(gè)挑選行為畏铆, 我們就需要
顯式聲明一個(gè)接口 ChoiceCircle 的實(shí)現(xiàn)類雷袋,于是我們可以考慮使用內(nèi)部匿名類,
進(jìn)入第三步辞居。
第三步
在實(shí)際使用時(shí)楷怒,我們不再聲明一個(gè)接口 ChoiceCircle 的實(shí)現(xiàn)類
匿名內(nèi)部類占用代碼空間較多,而且存在著模版代碼瓦灶,這種情況下鸠删,Lambda
表達(dá)式就可以派上用場(chǎng)了
所以可以把 Lambda 表達(dá)式看成匿名內(nèi)部類的一個(gè)簡(jiǎn)潔寫法
Lambda
在語法上,Lambda 表達(dá)式包含三個(gè)部分贼陶,參數(shù)列表刃泡,箭頭,主體碉怔,比如:
(parameters) -> expression
或
(parameters) -> {statements;}
Lambda 表達(dá)式用在函數(shù)式接口上捅僵,所謂函數(shù)式接口,是只定義了一個(gè)抽象
方法的接口(Interface)眨层,接口中是否有默認(rèn)方法庙楚,不影響。
注解@FunctionalInterface 可以幫助我們?cè)谠O(shè)計(jì)函數(shù)式接口時(shí)防止出錯(cuò)趴樱。
我們常用的 Runnable,Callable 都是函數(shù)式接口馒闷,JDK8 中新增了幾個(gè)函數(shù)式接
口:
Predicate<T> :
包含 test 方法酪捡,接受泛型的 T,返回 boolean纳账,可以視為斷言(檢查)接口
Consumer<T> :
包含 accept 方法逛薇,接受泛型的 T,無返回疏虫,可以視為數(shù)據(jù)消費(fèi)接口
Function<T永罚,R> :
包含 apply 方法,接受泛型的 T卧秘,返回 R呢袱,可以視為映射轉(zhuǎn)換接口
Supplier<T>
包含 get 方法,無輸入翅敌,返回 T羞福,可以視為創(chuàng)建一個(gè)新對(duì)象接口
UnaryOperator<T>
擴(kuò)展至 Function<T,T>蚯涮,所以這個(gè)本質(zhì)上也是一個(gè)映射轉(zhuǎn)換接口治专,只不過映
射轉(zhuǎn)換后的類型保持不變
BiFunction<T, U, R>
包含 apply 方法,接受泛型的 T遭顶、U张峰,返回 R,可以視為復(fù)合型映射轉(zhuǎn)換接口
BinaryOperator<T>
擴(kuò)展至 Function BiFunction<T,T,T>棒旗,所以這個(gè)本質(zhì)上也是一個(gè)復(fù)合型映射轉(zhuǎn)
換接口挟炬,只不過映射轉(zhuǎn)換后的類型保持不變
BiPredicate <T, U>
包含 test 方法,接受泛型的 T嗦哆,U谤祖,返回 boolean,可以視為復(fù)合型斷言(檢
查)接口
BiConsumer<T老速,U>:
包含 accept 方法粥喜,接受泛型的 T,U橘券,無返回额湘,可以視為復(fù)合型數(shù)據(jù)消費(fèi)接
口
同時(shí)還提供了一些為了防止自動(dòng)裝箱機(jī)制,而特意聲明的原始類型特化的函
數(shù)式接口旁舰,比如锋华,
在意義上,和對(duì)應(yīng)的 Predicate 接口并沒有差別箭窜。
函數(shù)描述符
函數(shù)式接口的抽象方法的簽名基本上就是 Lambda 表達(dá)式的簽名毯焕。我們將這
種抽象方法叫作函數(shù)描述符。
Runnable 接口可以看作一個(gè)什么也不接受什么也不返回(void)的函數(shù)的簽
名,因?yàn)樗挥幸粋€(gè)叫作 run 的抽象方法纳猫,這個(gè)方法什么也不接受婆咸,什么也不返
回(void)。
我們可以用 () -> void 代表參數(shù)列表為空芜辕,且返回 void 的函數(shù)尚骄。這正是
Runnable 接口所代表的。我們于是可以稱() -> void 是 Runnable 接口的函數(shù)描述
符侵续。
再考察 Callable 接口和 Supplier 接口
從函數(shù)描述符來看倔丈,Callable 接口和 Supplier 接口是一樣的,都是
() -> X
所以同一個(gè) Lambda 可以同時(shí)用在這兩個(gè)函數(shù)式接口上状蜗,比如:
Callable<Integer> = () -> 33;
Supplier<><Integer> = () -> 33;
擴(kuò)充知識(shí)點(diǎn)
Java并發(fā)編程(十一):Java8 新增的并發(fā)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來变姨,“玉大人族扰,你說我怎么就攤上這事《ㄅ罚” “怎么了渔呵?”我有些...
- 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)砍鸠。 經(jīng)常有香客問我扩氢,道長(zhǎng),這世上最難降的妖魔是什么爷辱? 我笑而不...
- 正文 為了忘掉前任录豺,我火速辦了婚禮,結(jié)果婚禮上饭弓,老公的妹妹穿的比我還像新娘双饥。我一直安慰自己,他們只是感情好弟断,可當(dāng)我...
- 文/花漫 我一把揭開白布咏花。 她就那樣靜靜地躺著,像睡著了一般阀趴。 火紅的嫁衣襯著肌膚如雪迟螺。 梳的紋絲不亂的頭發(fā)上冲秽,一...
- 文/蒼蘭香墨 我猛地睜開眼球订,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼后裸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起冒滩,我...
- 序言:老撾萬榮一對(duì)情侶失蹤微驶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后开睡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體因苹,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年篇恒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扶檐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
- 正文 年R本政府宣布,位于F島的核電站解虱,受9級(jí)特大地震影響颈嚼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜饭寺,卻給世界環(huán)境...
- 文/蒙蒙 一阻课、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧艰匙,春花似錦限煞、人聲如沸。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽油狂。三九已至店枣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓶蚂,已是汗流浹背。 一陣腳步聲響...
- 正文 我出身青樓征候,卻偏偏與公主長(zhǎng)得像杭攻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子疤坝,可洞房花燭夜當(dāng)晚...