自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java的NIO以及線程并發(fā)

開發(fā) 后端
NIO出現(xiàn)后,好像讓java的程序員有了楊眉吐氣的機會,怎么個吐氣法,當時大家是個什么感受,俺是不知道,因為當時俺不搞java,對java的認識有限。

一、NIO的出現(xiàn)

NIO是JDK1.4里面才出現(xiàn)的東東,他給大家?guī)淼?**好處是異步socket。其它file,pipe暫時就不多談了。

在JDK1.4出現(xiàn)之前,如果你需要編寫一個Java服務器,為了實現(xiàn)異步操作,你必須為每個連接請求生成一個Java線程,當連接請求很多時,線程的調度,上下文切換,所付出的代價是非常昂貴,而且由于Java是跨平臺的,各個平臺對線程的支持并不相同,性能也不相同,因此傳統(tǒng)的Java服務器編程架構是低效的且代價貴,dl大俠寫了個util.concurrent包后,總算是減輕了線程調度給java程序員帶來的痛苦,但是相比之與C、C++寫出來的服務器,java服務器在性能要求很高的情況下,基本上沒有什么競爭力,甚至是入圍的權利的都沒有。

二、異步socket的實現(xiàn)

NIO出現(xiàn)后,好像讓java的程序員有了楊眉吐氣的機會,怎么個吐氣法,當時大家是個什么感受,俺是不知道,因為當時俺不搞java,對java的認識有限。

NIO是一個基于事件的IO架構,最基本的思想就是:有事件我通知你,你再去做你的事情,沒事件時你大可以節(jié)約大把時間去做其它任何事情。而且NIO的主線程only one,不像傳統(tǒng)的模型,需要N個線程去,也減輕了JVM的工作量,使得JVM處理任務時顯得更加高效。

剛開始接觸NIO時,被N層的Channel架構、網(wǎng)上鋪天蓋地的好評給鎮(zhèn)住了,想想也應當是個很成熟的產品了,網(wǎng)上資料這么多,抄一抄Jetty、Tomcat以及其它一些牛B的源代碼,基本上就能搞定了,此時沒有想到大家受同步的影響這么深,也沒有想到連最基本的異步概念都沒有搞清楚就去寫代碼,搞出一堆的問題來(這是后話,后面再說)。

現(xiàn)在研究了NIO以后,發(fā)現(xiàn)NIO實際上在Java中做的工作是很簡單,就是將事件進行收集和分發(fā),我們結合一個經(jīng)典的調用例子來說明這個問題,我就不從NIO的基本使用說起了,大家可以查其它的資料,網(wǎng)上一大把。
當Channel注冊至Selector以后,我們的最經(jīng)典的調用方法,是這樣子的。

  1. while(somecondition) 
  2.         int n = selector.select(TIMEOUT); 
  3.         if(n == 0continue
  4.         for (Iterator iter = selector.selectedKeys().iterator(); iter.hasNext();) 
  5.         { 
  6.         if (key.isAcceptable()) 
  7.             doAcceptable(key); 
  8.         if (key.isConnectable()) 
  9.             doConnectable(key); 
  10.         if (key.isValid() && key.isReadable()) 
  11.             doReadable(key); 
  12.         if (key.isValid() && key.isWritable()) 
  13.             doWritable(key); 
  14.       iter.remove(); 
  15.     } 

這只是個小例子啊,什么異常我就懶得抓了。

nio中取得事件通知,就是在selector的select事件中完成的,在selector事件時有一個線程,這個線程具體的處理簡單點說就是:向操作系統(tǒng)詢問,selector中注冊的Channel&&SelectionKey的偶對各種事件是否有發(fā)生,如果有則添加到selector的selectedKeys屬性Set中去,并返回本次有多少個感興趣的事情發(fā)生。程序員發(fā)現(xiàn)這個值>0,表示有事件發(fā)生,馬上迭代selectedKeys中的SelectionKey,根據(jù)Key中的表示的事件,來做相應的處理。

實際上,這段說明表明了異步socket的核心,即異步socket不過是將多個socket的調度(或者還有他們的線程調度)全部交給操作系統(tǒng)自己去完成,異步的核心Selector,不過是將這些調度收集、分發(fā)而已。因為操作系統(tǒng)的socket、線程調度再咋D也比你JVM中要強,效率也高。

而且就算jvm做的和操作系統(tǒng)一樣好,性能一樣高(當然這是不現(xiàn)實的),使用異步socket你至少也節(jié)約了一半的系統(tǒng)消耗,想想假定操作系統(tǒng)本身也是使用線程來維護N個socket連接,在傳統(tǒng)的java編程中,你還必須為這些socket還多起一個java線程,那至少是2N個線程,現(xiàn)在只需要N+1。在高并發(fā)的情況下,你自己去想吧。

懂了這個道理,異步socket也就好寫了,也不會搞得思路混亂了。

三、 異步Socket中應當注意的事情

1. 讀

異步socket最基本的理念就是事件通知,前面也說了,有事件通知你了,你才該做你應當做的事情。在異步socket中當注冊了一個OP_READ事件后,你就等著Selector通知你吧,如果沒有通知你,你在家睡大覺都行。
在這里,我們有人出現(xiàn)的錯誤就是受同步的影響,自己去主動讀,而且還搞出了多線程,如果仔細考慮一下,就不會出現(xiàn)這個問題了。同步socket中,調用read方法讀取IO中的數(shù)據(jù)時,通常情況下如果沒有數(shù)據(jù)read方法會阻塞,且是同步的,所以當多個線程同時訪問時,read方法是線程安全的。

而在異步下就不同,異步是不會阻塞的,有什么就返回什么,你主動去讀,只要有數(shù)據(jù),你就可以拿走,在多線程的情況下,也許你是想讓***個線程讀取,but此時來數(shù)據(jù)時正好是線程2讀到了,那線程2就高高興興的拿去,而線程1還在苦苦等待,這樣導致數(shù)據(jù)混亂不說,如果后面再也不來數(shù)據(jù)了,線程1就是死循環(huán)啦。

2. 寫

在異步socket中,寫是唯一一個主動點的操作,但是也不能直接去寫Channel,而是應當先把自身注冊為OP_WRITABLE,這時Selector就會發(fā)現(xiàn)你的存在,并把給發(fā)一個write事件,你這時后就可以寫了,不過這時候有個小小的技巧,就是你執(zhí)行寫操作之前,請取消掉你的寫注冊,否則你的cpu肯定是100%。

3. 等待

在傳統(tǒng)的服務器編程中,由于對于每個請求都是產生的一個線程,因此你在你每個請求線程中wait也好,sleep也好,不會影響別人。但是異步不同,他的主線程只有一個,基本上每個處理都是線性的,也就是說處理完***個,然后才能處理第二個,因此nio是一個極好的處理短連接的架構。

我們現(xiàn)在出現(xiàn)的問題是,有人受同步的影響,沒有搞清異步是如何處理,竟然在方法處理中用上sleep,而且一等還是3秒,這意味著什么,3秒才能處理一個請求,My god,我要一個3秒才能處理一個請求的服務器干嘛啊,還是60年代?。海?/p>

如果出現(xiàn)這樣的需要等待的情況,應當另起一個線程(推薦使用線程池)去完成這個“長”時間的任務,或者將其它交給一個消息隊列,通過發(fā)消息的方式將給別人去完成也行,客戶端能等,你服務器怎么也能等呢?寫出這樣的代碼,基本上一個服務器也就廢了。

原文鏈接:http://www.cnblogs.com/sunwei2012/archive/2010/02/11/1667501.html

【編輯推薦】

  1. 基于事件的NIO多線程服務器
  2. Java NIO的多路復用及reactor
  3. 在Java中使用NIO進行網(wǎng)絡編程
  4. Java NIO非阻塞服務器示例
  5. 基于Java NIO的即時聊天服務器模型
責任編輯:林師授 來源: 玩玩樂樂的博客
相關推薦

2010-01-28 09:55:05

性能優(yōu)化

2019-06-03 09:13:11

線程進程多線程

2018-09-19 14:53:02

NIOBIO運行

2011-12-29 13:31:15

Java

2025-02-19 00:05:18

Java并發(fā)編程

2020-09-04 10:29:47

Java線程池并發(fā)

2025-02-17 00:00:25

Java并發(fā)編程

2023-08-01 08:27:15

Java I/ONIO

2011-12-08 13:04:06

JavaNIO

2011-12-07 16:12:29

JavaNIO

2011-12-15 11:03:21

JavaNIO

2025-02-06 03:14:38

2025-01-10 07:10:00

2009-12-14 10:44:51

Java 7NIO2

2023-12-08 08:07:48

Java 21虛擬線程

2010-05-04 08:44:42

Java并發(fā)模型

2024-12-31 09:00:12

Java線程狀態(tài)

2021-06-29 07:47:23

多線程協(xié)作數(shù)據(jù)

2019-11-07 09:20:29

Java線程操作系統(tǒng)

2019-09-16 08:45:53

并發(fā)編程通信
點贊
收藏

51CTO技術棧公眾號