您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關如何利用CountDownLatch實現基于netty的BIO,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
Netty是一個NIO客戶端-服務器框架,在NIO模式下,線程直接返回結果,當緩沖區準備好數據之后再異步線程回調客戶端消息處理。不會像BIO一樣阻塞線程(I/O)并持續等待被調用方準備好響應數據才返回。
但是在某些使用socket通訊的場景下,使用了NIO的netty,但是調用方必須在當前線程等待服務返回業務處理狀態之后才能進行后續的操作,那么就需要用到BIO模式,那么除了使用java原生的BIO,這里介紹一種使用CountDownLatch+Netty來模擬BIO的實現。
下面介紹下實現過程和偽代碼,文章末尾提供完整示例下載地址。代碼僅供學習。
環境:netty4.1.27、eclipse,jdk1.8;
流程設計
原理說明
1、在客戶端發送數據給服務端時(本實例服務端采用java原生socket簡單實現),通過uuid生成本次發送的請求的唯一標識(sn),并將此sn附在發送數據的頭部位置(服務端返回時需要帶上此sn),同時客戶端產生一個CountDownLatch和當前sn綁定。
2、發送成功后,通過CountDownLatch.await阻塞當前線程。
3、服務端接收數據并處理相關完后,封裝含客戶端sn的返回數據發送給客戶端,客戶端接收到服務端返回的信息后,根據返回的sn獲取到對應的CountDownLatch,并調用countDown使得上一步阻塞的線程能夠繼續進行后續業務操作。
關鍵代碼片段
發送消息
/*** 發送消息* @param msg*/public void sendMsg(String ip,int port,String msg) { try { //1 連接到服務端,如果長連接可以修改此邏輯 connectToServer(ip, port); //2生成阻塞計數器 String sn = UUID.randomUUID().toString(); Receiver.addWait(sn); //3 發送數據 client.channel().writeAndFlush(sn+"@"+msg+"END").sync();//加end防止粘包 LOG.info("發送消息成功,msg:"+msg); //4 等待接接收到消息后,計數器countdown。 Receiver.block(sn);//可以設置等待時間,以防止線程長時間阻塞。 //5處理服務端返回 handlerServerAnswer(sn); } catch (Exception e) { LOG.error("處理消息失敗.",e); }}
接收消息
/** * 處理服務端返回消息 */@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { try { String dataFromServer = (String) msg; String[] snData = dataFromServer.split("@"); String sn = snData[0]; String data = snData[1]; response.put(sn, data);//等待業務邏輯消費 if(!waitLatch.containsKey(sn)) { LOG.error("非法sn:"+sn); return; } waitLatch.get(sn).countDown();//取消阻塞,讓發送線程后續邏輯運行。 waitLatch.remove(sn); } catch (Exception e) { LOG.error("接收到非法數據:"+msg); } }
服務端代碼
/*** 模擬服務端* @param args* @throws Exception*/public static void main( String[] args ) throws Exception { serverSocket = new ServerSocket(PORT); LOG.info("服務監聽啟動,端口:"+PORT); while(true) { try { Socket socket = serverSocket.accept(); InputStream in = socket.getInputStream(); int len; StringBuffer sb = new StringBuffer(); byte[] bytes = new byte[1024]; while((len = in.read(bytes))!=-1) { String bytesData = new String(bytes,0,len,"utf-8"); sb.append(bytesData); if(bytesData.endsWith("END")) { //處理業務邏輯并返回消息 handMsgAndResponse(socket,sb.toString()); sb = null; } } } catch (Exception e) { LOG.error("處理客戶端消息失敗.",e); } Thread.sleep(1000); } }
看完上述內容,你們對如何利用CountDownLatch實現基于netty的BIO有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。