Java核心-深入理解BIO泉手、NIO斩萌、AIO

導(dǎo)讀:本文你將獲取到:同/異步 + 阻/非阻塞的性能區(qū)別术裸;BIO亭枷、NIO叨粘、AIO 的區(qū)別瘤睹;理解和實(shí)現(xiàn) NIO 操作 Socket 時(shí)的多路復(fù)用轰传;同時(shí)掌握 IO 最底層最核心的操作技巧获茬。

BIO倔既、NIO渤涌、AIO 的區(qū)別是什么把还?

同/異步吊履、阻/非阻塞的區(qū)別是什么?

文件讀寫(xiě)最優(yōu)雅的實(shí)現(xiàn)方式是什么酌伊?

NIO 如何實(shí)現(xiàn)多路復(fù)用功能腺晾?

帶著以上這幾個(gè)問(wèn)題辜贵,讓我們一起進(jìn)入IO的世界吧。

在開(kāi)始之前鼻由,我們先來(lái)思考一個(gè)問(wèn)題:我們經(jīng)常所說(shuō)的“IO”的全稱(chēng)到底是什么厚棵?

可能很多人看到這個(gè)問(wèn)題和我一樣一臉懵逼婆硬,IO的全稱(chēng)其實(shí)是:Input/Output的縮寫(xiě)。

一向楼、IO 介紹

我們通常所說(shuō)的 BIO 是相對(duì)于 NIO 來(lái)說(shuō)的谐区,BIO 也就是 Java 開(kāi)始之初推出的 IO 操作模塊,BIO 是 BlockingIO 的縮寫(xiě)昭抒,顧名思義就是阻塞 IO 的意思灭返。

1.1 BIO、NIO诈乒、AIO的區(qū)別

BIO 就是傳統(tǒng)的 java.io 包怕磨,它是基于流模型實(shí)現(xiàn)的,交互的方式是同步消约、阻塞方式肠鲫,也就是說(shuō)在讀入輸入流或者輸出流時(shí),在讀寫(xiě)動(dòng)作完成之前或粮,線程會(huì)一直阻塞在那里导饲,它們之間的調(diào)用時(shí)可靠的線性順序。它的有點(diǎn)就是代碼比較簡(jiǎn)單氯材、直觀渣锦;缺點(diǎn)就是 IO 的效率和擴(kuò)展性很低,容易成為應(yīng)用性能瓶頸氢哮。

NIO 是 Java 1.4 引入的 java.nio 包,提供了 Channel听盖、Selector、Buffer 等新的抽象背零,可以構(gòu)建多路復(fù)用的蝎困、同步非阻塞 IO 程序,同時(shí)提供了更接近操作系統(tǒng)底層高性能的數(shù)據(jù)操作方式虽缕。

AIO 是 Java 1.7 之后引入的包伍派,是 NIO 的升級(jí)版本诉植,提供了異步非堵塞的 IO 操作方式,所以人們叫它 AIO(Asynchronous IO)灼擂,異步 IO 是基于事件和回調(diào)機(jī)制實(shí)現(xiàn)的剔应,也就是應(yīng)用操作之后會(huì)直接返回,不會(huì)堵塞在那里纤控,當(dāng)后臺(tái)處理完成嚼黔,操作系統(tǒng)會(huì)通知相應(yīng)的線程進(jìn)行后續(xù)的操作。

1.2 全面認(rèn)識(shí) IO

傳統(tǒng)的 IO 大致可以分為4種類(lèi)型:

InputStream碎节、OutputStream 基于字節(jié)操作的 IO

Writer狮荔、Reader 基于字符操作的 IO

File 基于磁盤(pán)操作的 IO

Socket 基于網(wǎng)絡(luò)操作的 IO

java.net 下提供的 Scoket 很多時(shí)候人們也把它歸為 同步阻塞 IO ,因?yàn)榫W(wǎng)絡(luò)通訊同樣是 IO 行為。

java.io 下的類(lèi)和接口很多雅采,但大體都是 InputStream宝鼓、OutputStream愚铡、Writer、Reader 的子集营曼,所有掌握這4個(gè)類(lèi)和File的使用蒂阱,是用好 IO 的關(guān)鍵。

1.3 IO 使用

接下來(lái)看 InputStream妈踊、OutputStream廊营、Writer、Reader 的繼承關(guān)系圖和使用示例慎式。

1.3.1 InputStream 使用

繼承關(guān)系圖和類(lèi)方法,如下圖:

InputStream 使用示例:

InputStream inputStream =newFileInputStream("D:\\log.txt");byte[] bytes =newbyte[inputStream.available()];inputStream.read(bytes);String str =newString(bytes,"utf-8");System.out.println(str);inputStream.close();

1.3.2 OutputStream 使用

繼承關(guān)系圖和類(lèi)方法,如下圖:

OutputStream 使用示例:

OutputStream outputStream =newFileOutputStream("D:\\log.txt",true);// 參數(shù)二扇救,表示是否追加,true=追加outputStream.write("你好沧烈,老王".getBytes("utf-8"));outputStream.close();

1.3.3 Writer 使用

Writer 繼承關(guān)系圖和類(lèi)方法,如下圖:

Writer 使用示例:

Writer writer =newFileWriter("D:\\log.txt",true);// 參數(shù)二,是否追加文件侈贷,true=追加writer.append("老王撑蚌,你好");writer.close();

1.3.4 Reader 使用

Reader 繼承關(guān)系圖和類(lèi)方法,如下圖:

Reader 使用示例:

Reader reader =newFileReader(filePath);BufferedReader bufferedReader =newBufferedReader(reader);StringBufferbf =newStringBuffer();Stringstr;while((str = bufferedReader.readLine()) !=null) {? ? bf.append(str +"\n");}bufferedReader.close();reader.close();System.out.println(bf.toString());

二亮垫、同步、異步害晦、阻塞壹瘟、非阻塞

上面說(shuō)了很多關(guān)于同步、異步雕凹、阻塞和非阻塞的概念线欲,接下來(lái)就具體聊一下它們4個(gè)的含義苦锨,以及組合之后形成的性能分析。

2.1 同步與異步

同步就是一個(gè)任務(wù)的完成需要依賴(lài)另外一個(gè)任務(wù)時(shí)秃励,只有等待被依賴(lài)的任務(wù)完成后,依賴(lài)的任務(wù)才能算完成谣旁,這是一種可靠的任務(wù)序列。要么成功都成功杆麸,失敗都失敗饼问,兩個(gè)任務(wù)的狀態(tài)可以保持一致。而異步是不需要等待被依賴(lài)的任務(wù)完成盅视,只是通知被依賴(lài)的任務(wù)要完成什么工作,依賴(lài)的任務(wù)也立即執(zhí)行贺归,只要自己完成了整個(gè)任務(wù)就算完成了。至于被依賴(lài)的任務(wù)最終是否真正完成踱葛,依賴(lài)它的任務(wù)無(wú)法確定光坝,所以它是不可靠的任務(wù)序列洲赵。我們可以用打電話和發(fā)短信來(lái)很好的比喻同步與異步操作芝发。

2.2 阻塞與非阻塞

阻塞與非阻塞主要是從 CPU 的消耗上來(lái)說(shuō)的腹殿,阻塞就是 CPU 停下來(lái)等待一個(gè)慢的操作完成 CPU 才接著完成其它的事刻炒。非阻塞就是在這個(gè)慢的操作在執(zhí)行時(shí) CPU 去干其它別的事拇厢,等這個(gè)慢的操作完成時(shí)管行,CPU 再接著完成后續(xù)的操作。雖然表面上看非阻塞的方式可以明顯的提高 CPU 的利用率废赞,但是也帶了另外一種后果就是系統(tǒng)的線程切換增加。增加的 CPU 使用時(shí)間能不能補(bǔ)償系統(tǒng)的切換成本需要好好評(píng)估耘沼。

2.3 同/異、阻/非堵塞 組合

同/異、阻/非堵塞的組合者春,有四種類(lèi)型校仑,如下表:

組合方式性能分析

同步阻塞最常用的一種用法稻扬,使用也是最簡(jiǎn)單的,但是 I/O 性能一般很差,CPU 大部分在空閑狀態(tài)黔宛。

同步非阻塞提升 I/O 性能的常用手段,就是將 I/O 的阻塞改成非阻塞方式案淋,尤其在網(wǎng)絡(luò) I/O 是長(zhǎng)連接,同時(shí)傳輸數(shù)據(jù)也不是很多的情況下,提升性能非常有效旨涝。 這種方式通常能提升 I/O 性能贩耐,但是會(huì)增加CPU 消耗,要考慮增加的 I/O 性能能不能補(bǔ)償 CPU 的消耗,也就是系統(tǒng)的瓶頸是在 I/O 還是在 CPU 上奇钞。

異步阻塞這種方式在分布式數(shù)據(jù)庫(kù)中經(jīng)常用到,例如在網(wǎng)一個(gè)分布式數(shù)據(jù)庫(kù)中寫(xiě)一條記錄,通常會(huì)有一份是同步阻塞的記錄,而還有兩至三份是備份記錄會(huì)寫(xiě)到其它機(jī)器上册着,這些備份記錄通常都是采用異步阻塞的方式寫(xiě) I/O。異步阻塞對(duì)網(wǎng)絡(luò) I/O 能夠提升效率,尤其像上面這種同時(shí)寫(xiě)多份相同數(shù)據(jù)的情況。

異步非阻塞這種組合方式用起來(lái)比較復(fù)雜,只有在一些非常復(fù)雜的分布式情況下使用,像集群之間的消息同步機(jī)制一般用這種 I/O 組合方式伞租。如 Cassandra 的 Gossip 通信機(jī)制就是采用異步非阻塞的方式作喘。它適合同時(shí)要傳多份相同的數(shù)據(jù)到集群中不同的機(jī)器广辰,同時(shí)數(shù)據(jù)的傳輸量雖然不大,但是卻非常頻繁。這種網(wǎng)絡(luò) I/O 用這個(gè)方式性能能達(dá)到最高夯接。

三逊拍、優(yōu)雅的文件讀寫(xiě)

Java 7 之前文件的讀取是這樣的:

// 添加文件FileWriter fileWriter =newFileWriter(filePath,true);fileWriter.write(Content);fileWriter.close();// 讀取文件FileReader fileReader =newFileReader(filePath);BufferedReader bufferedReader =newBufferedReader(fileReader);StringBuffer bf =newStringBuffer();String str;while ((str = bufferedReader.readLine()) != null) {? ? bf.append(str +"\n");}bufferedReader.close();fileReader.close();System.out.println(bf.toString());

Java 7 引入了Files(java.nio包下)的世曾,大大簡(jiǎn)化了文件的讀寫(xiě),如下:

// 寫(xiě)入文件(追加方式:StandardOpenOption.APPEND)Files.write(Paths.get(filePath), Content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);// 讀取文件byte[]data= Files.readAllBytes(Paths.get(filePath));System.out.println(new String(data, StandardCharsets.UTF_8));

讀寫(xiě)文件都是一行代碼搞定,沒(méi)錯(cuò)這就是最優(yōu)雅的文件操作玫恳。

Files 下還有很多有用的方法,比如創(chuàng)建多層文件夾,寫(xiě)法上也簡(jiǎn)單了:

// 創(chuàng)建多(單)層目錄(如果不存在創(chuàng)建换吧,存在不會(huì)報(bào)錯(cuò))newFile("D://a//b").mkdirs();

四贯莺、Socket 和 NIO 的多路復(fù)用

本節(jié)帶你實(shí)現(xiàn)最基礎(chǔ)的 Socket 的同時(shí)爹耗,同時(shí)會(huì)實(shí)現(xiàn) NIO 多路復(fù)用,還有 AIO 中 Socket 的實(shí)現(xiàn)。

4.1 傳統(tǒng)的 Socket 實(shí)現(xiàn)

接下來(lái)我們將會(huì)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 Socket炫狱,服務(wù)器端只發(fā)給客戶端信息,再由客戶端打印出來(lái)的例子汪茧,代碼如下:

intport =4343;//端口號(hào)// Socket 服務(wù)器端(簡(jiǎn)單的發(fā)送信息)Thread sThread =newThread(newRunnable() {@Overridepublicvoidrun(){try{? ? ? ? ? ? ServerSocket serverSocket =newServerSocket(port);while(true) {// 等待連接Socket socket = serverSocket.accept();? ? ? ? ? ? ? ? Thread sHandlerThread =newThread(newRunnable() {@Overridepublicvoidrun(){try(PrintWriter printWriter =newPrintWriter(socket.getOutputStream())) {? ? ? ? ? ? ? ? ? ? ? ? ? ? printWriter.println("hello world!");? ? ? ? ? ? ? ? ? ? ? ? ? ? printWriter.flush();? ? ? ? ? ? ? ? ? ? ? ? }catch(IOException e) {? ? ? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? });? ? ? ? ? ? ? ? sHandlerThread.start();? ? ? ? ? ? }? ? ? ? }catch(IOException e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? }? ? }});sThread.start();// Socket 客戶端(接收信息并打又椴濉)try(Socket cSocket =newSocket(InetAddress.getLocalHost(), port)) {? ? BufferedReader bufferedReader =newBufferedReader(newInputStreamReader(cSocket.getInputStream()));? ? bufferedReader.lines().forEach(s -> System.out.println("客戶端:"+ s));}catch(UnknownHostException e) {? ? e.printStackTrace();}catch(IOException e) {? ? e.printStackTrace();}

調(diào)用 accept 方法训堆,阻塞等待客戶端連接鲁沥;

利用 Socket 模擬了一個(gè)簡(jiǎn)單的客戶端,只進(jìn)行連接允扇、讀取和打雍巍;

在 Java 中赃蛛,線程的實(shí)現(xiàn)是比較重量級(jí)的,所以線程的啟動(dòng)或者銷(xiāo)毀是很消耗服務(wù)器的資源的,即使使用線程池來(lái)實(shí)現(xiàn)实束,使用上述傳統(tǒng)的 Socket 方式悼瘾,當(dāng)連接數(shù)極具上升也會(huì)帶來(lái)性能瓶頸,原因是線程的上線文切換開(kāi)銷(xiāo)會(huì)在高并發(fā)的時(shí)候體現(xiàn)的很明顯,并且以上操作方式還是同步阻塞式的編程,性能問(wèn)題在高并發(fā)的時(shí)候就會(huì)體現(xiàn)的尤為明顯富稻。

以上的流程向抢,如下圖:

4.2 NIO 多路復(fù)用

介于以上高并發(fā)的問(wèn)題,NIO 的多路復(fù)用功能就顯得意義非凡了。

NIO 是利用了單線程輪詢事件的機(jī)制,通過(guò)高效地定位就緒的 Channel徙鱼,來(lái)決定做什么距淫,僅僅 select 階段是阻塞的蓬衡,可以有效避免大量客戶端連接時(shí)盟猖,頻繁線程切換帶來(lái)的問(wèn)題惊豺,應(yīng)用的擴(kuò)展能力有了非常大的提高萍程。

// NIO 多路復(fù)用ThreadPoolExecutor threadPool =newThreadPoolExecutor(4,4,60L, TimeUnit.SECONDS,newLinkedBlockingQueue());threadPool.execute(newRunnable() {? ? @Overridepublicvoidrun(){try(Selector selector = Selector.open();? ? ? ? ? ? ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();) {? ? ? ? ? ? serverSocketChannel.bind(newInetSocketAddress(InetAddress.getLocalHost(), port));? ? ? ? ? ? serverSocketChannel.configureBlocking(false);? ? ? ? ? ? serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);while(true) {? ? ? ? ? ? ? ? selector.select();// 阻塞等待就緒的ChannelSet selectionKeys = selector.selectedKeys();? ? ? ? ? ? ? ? Iterator iterator = selectionKeys.iterator();while(iterator.hasNext()) {? ? ? ? ? ? ? ? ? ? SelectionKey key = iterator.next();try(SocketChannel channel = ((ServerSocketChannel) key.channel()).accept()) {? ? ? ? ? ? ? ? ? ? ? ? channel.write(Charset.defaultCharset().encode("你好朽褪,世界"));? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? iterator.remove();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }catch(IOException e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? }? ? }});// Socket 客戶端(接收信息并打印)try(Socket cSocket =newSocket(InetAddress.getLocalHost(), port)) {? ? BufferedReader bufferedReader =newBufferedReader(newInputStreamReader(cSocket.getInputStream()));? ? bufferedReader.lines().forEach(s -> System.out.println("NIO 客戶端:"+ s));}catch(IOException e) {? ? e.printStackTrace();}

首先,通過(guò) Selector.open() 創(chuàng)建一個(gè) Selector输莺,作為類(lèi)似調(diào)度員的角色疏唾;

然后祖灰,創(chuàng)建一個(gè) ServerSocketChannel,并且向 Selector 注冊(cè)畔规,通過(guò)指定 SelectionKey.OP_ACCEPT局扶,告訴調(diào)度員,它關(guān)注的是新的連接請(qǐng)求叁扫;

為什么我們要明確配置非阻塞模式呢三妈?這是因?yàn)樽枞J较拢?cè)操作是不允許的莫绣,會(huì)拋出 IllegalBlockingModeException 異常畴蒲;

Selector 阻塞在 select 操作,當(dāng)有 Channel 發(fā)生接入請(qǐng)求对室,就會(huì)被喚醒模燥;

下面的圖,可以有效的說(shuō)明 NIO 復(fù)用的流程:

就這樣 NIO 的多路復(fù)用就大大提升了服務(wù)器端響應(yīng)高并發(fā)的能力掩宜。

4.3 AIO 版 Socket 實(shí)現(xiàn)

Java 1.7 提供了 AIO 實(shí)現(xiàn)的 Socket 是這樣的蔫骂,如下代碼:

// AIO線程復(fù)用版Thread sThread =newThread(newRunnable() {? ? @Overridepublicvoidrun() {? ? ? ? AsynchronousChannelGroupgroup=null;try{group= AsynchronousChannelGroup.withThreadPool(Executors.newFixedThreadPool(4));? ? ? ? ? ? AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open(group).bind(newInetSocketAddress(InetAddress.getLocalHost(), port));? ? ? ? ? ? server.accept(null,newCompletionHandler() {? ? ? ? ? ? ? ? @Overridepublicvoidcompleted(AsynchronousSocketChannel result, AsynchronousServerSocketChannel attachment) {? ? ? ? ? ? ? ? ? ? server.accept(null,this);// 接收下一個(gè)請(qǐng)求try{? ? ? ? ? ? ? ? ? ? ? ? Future f = result.write(Charset.defaultCharset().encode("你好,世界"));? ? ? ? ? ? ? ? ? ? ? ? f.get();? ? ? ? ? ? ? ? ? ? ? ? System.out.println("服務(wù)端發(fā)送時(shí)間:"+newSimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(newDate()));? ? ? ? ? ? ? ? ? ? ? ? result.close();? ? ? ? ? ? ? ? ? ? }catch(InterruptedException | ExecutionException | IOException e) {? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? @Overridepublicvoidfailed(Throwable exc, AsynchronousServerSocketChannel attachment) {? ? ? ? ? ? ? ? }? ? ? ? ? ? });group.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);? ? ? ? }catch(IOException | InterruptedException e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? }? ? }});sThread.start();// Socket 客戶端AsynchronousSocketChannel client = AsynchronousSocketChannel.open();Future future = client.connect(newInetSocketAddress(InetAddress.getLocalHost(), port));future.get();ByteBuffer buffer = ByteBuffer.allocate(100);client.read(buffer,null,newCompletionHandler() {? ? @Overridepublicvoidcompleted(Integer result,Voidattachment) {? ? ? ? System.out.println("客戶端打游馈:"+newString(buffer.array()));? ? }? ? @Overridepublicvoidfailed(Throwable exc,Voidattachment) {? ? ? ? exc.printStackTrace();try{? ? ? ? ? ? client.close();? ? ? ? }catch(IOException e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? }? ? }});Thread.sleep(10*1000);

五辽旋、總結(jié)

以上基本就是 IO 從 1.0 到目前版本(本文的版本)JDK 8 的核心使用操作了,可以看出來(lái) IO 作為比較常用的基礎(chǔ)功能,發(fā)展變化的改動(dòng)也很大补胚,而且使用起來(lái)也越來(lái)越簡(jiǎn)單了固该,IO 的操作也是比較好理解的,一個(gè)輸入一個(gè)輸出糖儡,掌握好了輸入輸出也就掌握好了 IO,Socket 作為網(wǎng)絡(luò)交互的集成功能怔匣,顯然 NIO 的多路復(fù)用握联,給 Socket 帶來(lái)了更多的活力和選擇,用戶可以根據(jù)自己的實(shí)際場(chǎng)景選擇相應(yīng)的代碼策略每瞒。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末金闽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子剿骨,更是在濱河造成了極大的恐慌代芜,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浓利,死亡現(xiàn)場(chǎng)離奇詭異挤庇,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)贷掖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)嫡秕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人苹威,你說(shuō)我怎么就攤上這事昆咽。” “怎么了牙甫?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵掷酗,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我窟哺,道長(zhǎng)泻轰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任脏答,我火速辦了婚禮糕殉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘殖告。我一直安慰自己阿蝶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布黄绩。 她就那樣靜靜地躺著羡洁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪爽丹。 梳的紋絲不亂的頭發(fā)上筑煮,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天辛蚊,我揣著相機(jī)與錄音,去河邊找鬼真仲。 笑死袋马,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的秸应。 我是一名探鬼主播虑凛,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼软啼!你這毒婦竟也來(lái)了桑谍?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤祸挪,失蹤者是張志新(化名)和其女友劉穎锣披,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體贿条,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雹仿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了整以。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盅粪。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖悄蕾,靈堂內(nèi)的尸體忽然破棺而出票顾,到底是詐尸還是另有隱情,我是刑警寧澤帆调,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布奠骄,位于F島的核電站,受9級(jí)特大地震影響番刊,放射性物質(zhì)發(fā)生泄漏含鳞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一芹务、第九天 我趴在偏房一處隱蔽的房頂上張望蝉绷。 院中可真熱鬧,春花似錦枣抱、人聲如沸熔吗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)桅狠。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間中跌,已是汗流浹背咨堤。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留漩符,地道東北人一喘。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像嗜暴,于是被迫代替她去往敵國(guó)和親津滞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

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