【轉載】Java非同步通訊收藏
程式碼號為”Merlin”的J2SE1.4帶來了一些激動人心的新特性,諸如對正規表示式的支援,非同步輸入輸出流,通道(Channel),字符集等.雖然該版本還處在測試階段,但這些新特性早已讓開發人員們躍躍欲試.在Merlin釋出之前,非同步輸入輸出流的應用還只是C,C++程式設計師的特殊武器;在 Merlin中引入非同步輸入輸出機制之後,Java程式設計師也可以利用它完成很多簡潔卻是高質量的程式碼了.本文將介紹怎樣使用非同步輸入輸出流來編寫 Socket程式通訊程式.
在Merlin之前,編寫Socket程式是比較繁瑣的工作.因為輸入輸出都必須同步.這樣,對於多客戶端客戶/伺服器模式,不得不使用多執行緒.即為每個連線的客戶都分配一個執行緒來處理輸入輸出.由此而帶來的問題是可想而知的.程式設計師不得不為了避免死鎖,執行緒安全等問題,進行大量的編碼和測試.很多人都在抱怨為什麼不在Java中引入非同步輸入輸出機制.比較官方的解釋是,任何一種應用程式介面的引入,都必須相容任何操作平臺.因為Java是跨平臺的.而當時支援非同步輸入輸出機制的操作平臺顯然不可能是全部.自Java 2 Platform以後,分離出J2SE,J2ME,J2EE三種不同型別的應用程式介面,以適應不同的應用開發.Java標準的制訂者們意識到了這個問題,並且支援非同步輸入輸出機制的操作平臺在當今操作平臺中處於主流地位.於是,Jdk(J2SE) 的第五次釋出中引入了非同步輸入輸出機制.
以前的Socket程式通訊程式設計中,一般客戶端和伺服器端程式設計如下:
- 伺服器端:
//伺服器端監聽執行緒 |
- 客戶端:
............ |
- 以上程式碼段只是用同步機制編寫Socket程式通訊的一個框架,實際上要考慮的問題要複雜的多(有興趣的讀者可以參考我的一篇文章《Internet 實時通訊系統設計與實現》)。將這樣一個框架列出來,只是為了與用非同步機制實現的Socket程式通訊進行比較。下面將介紹使用非同步機制的程式設計。
|
|
用非同步輸入輸出流編寫Socket程式通訊程式
在Merlin中加入了用於實現非同步輸入輸出機制的應用程式介面包:java.nio(新的輸入輸出包,定義了很多基本型別緩衝(Buffer)), java.nio.channels(通道及選擇器等,用於非同步輸入輸出),java.nio.charset(字元的編碼解碼)。通道 (Channel)首先在選擇器(Selector)中註冊自己感興趣的事件,當相應的事件發生時,選擇器便通過選擇鍵(SelectionKey)通知已註冊的通道。然後通道將需要處理的資訊,通過緩衝(Buffer)打包,編碼/解碼,完成輸入輸出控制。
這裡主要介紹ServerSocketChannel和 SocketChannel.它們都是可選擇的(selectable)通道,分別可以工作在同步和非同步兩種方式下(注意,這裡的可選擇不是指可以選擇兩種工作方式,而是指可以有選擇的註冊自己感興趣的事件)。可以用channel.configureBlocking(Boolean )來設定其工作方式。與以前版本的API相比較,ServerSocketChannel就相當於ServerSocket (ServerSocketChannel封裝了ServerSocket),而SocketChannel就相當於Socket (SocketChannel封裝了Socket)。當通道工作在同步方式時,程式設計方法與以前的基本相似,這裡主要介紹非同步工作方式。
所謂非同步輸入輸出機制,是指在進行輸入輸出處理時,不必等到輸入輸出處理完畢才返回。所以非同步的同義語是非阻塞(None Blocking)。在伺服器端,ServerSocketChannel通過靜態函式open()返回一個例項serverChl。然後該通道呼叫 serverChl.socket().bind()繫結到伺服器某埠,並呼叫register(Selector sel, SelectionKey.OP_ACCEPT)註冊OP_ACCEPT事件到一個選擇器中(ServerSocketChannel只可以註冊 OP_ACCEPT事件)。當有客戶請求連線時,選擇器就會通知該通道有客戶連線請求,就可以進行相應的輸入輸出控制了;在客戶端,clientChl例項註冊自己感興趣的事件後(可以是OP_CONNECT,OP_READ,OP_WRITE的組合),呼叫clientChl.connect (InetSocketAddress )連線伺服器然後進行相應處理。注意,這裡的連線是非同步的,即會立即返回而繼續執行後面的程式碼。
選擇器(Selector)的作用是:將通道感興趣的事件放入佇列中,而不是馬上提交給應用程式,等已註冊的通道自己來請求處理這些事件。換句話說,就是選擇器將會隨時報告已經準備好了的通道,而且是按照先進先出的順序。那麼,選擇器是通過什麼來報告的呢?選擇鍵(SelectionKey)。選擇鍵的作用就是表明哪個通道已經做好了準備,準備幹什麼。你也許馬上會想到,那一定是已註冊的通道感興趣的事件。不錯,例如對於伺服器端serverChl來說,可以呼叫key.isAcceptable()來通知serverChl有客戶端連線請求。相應的函式還有: SelectionKey.isReadable(),SelectionKey.isWritable()。一般的,在一個迴圈中輪詢感興趣的事件(具體可參照下面的程式碼)。如果選擇器中尚無通道已註冊事件發生,呼叫Selector.select()將阻塞,直到有事件發生為止。另外,可以呼叫 selectNow()或者select(long timeout)。前者立即返回,沒有事件時返回0值;後者等待timeout時間後返回。一個選擇器最多可以同時被63個通道一起註冊使用。
下面是用非同步輸入輸出機制實現的客戶/伺服器例項程式�D�D程式清單1(限於篇幅,只給出了伺服器端實現,讀者可以參照著實現客戶端程式碼):
public class NBlockingServer { |
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7389553/viewspace-619657/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 同步通訊和非同步通訊非同步
- 同步、非同步通訊非同步
- IO通訊模型(二)同步非阻塞模式NIO(NonBlocking IO)模型模式BloC
- RabbitMQ 入門(一)同步通訊和非同步通訊MQ非同步
- java同步非阻塞IOJava
- [轉]阻塞/非阻塞與同步/非同步非同步
- 由轉載開始—通訊—Mathworks
- Thinking in Java--使用NIO實現非阻塞Socket通訊ThinkingJava
- Java 非阻塞 IO 和非同步 IOJava非同步
- Java入門系列-25-NIO(實現非阻塞網路通訊)Java
- 【轉載】通訊長連線與短連線
- Java Nio通訊Java
- Python非同步通訊模組asynchatPython非同步
- Python非同步通訊模組asyncorePython非同步
- 從同步原語看非阻塞同步以及Java中的應用Java
- 如何解讀 Java IO、NIO 中的同步阻塞與同步非阻塞?Java
- 同步非同步,阻塞非阻塞非同步
- 非同步、同步、阻塞、非阻塞非同步
- 同步、非同步、阻塞、非阻塞非同步
- Socket程式設計中的同步、非同步、阻塞和非阻塞(轉)程式設計非同步
- Java併發技術05:傳統執行緒同步通訊技術Java執行緒
- 串列埠通訊 (轉)串列埠
- 轉:Java同步技術Java
- C#入門程式碼[轉載][收藏]C#
- vue 元件通訊總結 (非vuex和Event Bus)Vue元件
- 3.Vue非父子元件之間的通訊Vue元件
- Android跨程式通訊之非AIDL(二)AndroidAI
- 同步非同步 與 阻塞非阻塞非同步
- 理解阻塞、非阻塞、同步、非同步非同步
- 同步、非同步,阻塞、非阻塞理解非同步
- 同步、非同步、阻塞與非阻塞非同步
- 同步、非同步、阻塞和非阻塞非同步
- 深入 Java 類載入全流程,值得你收藏Java
- 轉載非域模式下禁用程式模式
- java實現UDP通訊JavaUDP
- Java執行緒通訊Java執行緒
- 同步和非同步關注的是訊息通訊機制,阻塞和非阻塞關注的是程式在等待呼叫結果(訊息,返回值)時的狀態非同步
- Java多執行緒/併發11、執行緒同步通訊:notify、waitJava執行緒AI