久久国产精品一区二区三区四区,久色婷婷小香蕉久久,国产日韩欧美在线播放不卡,另类av一区二区

視訊!IO流中「線程」模型總結
來源:知了一笑    時間:2023-04-07 08:57:06
一、基礎簡介

在IO流的網絡模型中,以常見的「客戶端-服務端」交互場景為例;

客戶端與服務端進行通信「交互」,可能是同步或者異步,服務端進行「流」處理時,可能是阻塞或者非阻塞模式,當然也有自定義的業務流程需要執行,從處理邏輯看就是「讀取數據-業務執行-應答寫數據」的形式;

Java提供「三種」IO網絡編程模型,即:「BIO同步阻塞」、「NIO同步非阻塞」、「AIO異步非阻塞」;


(資料圖片僅供參考)

二、同步阻塞1、模型圖解

BIO即同步阻塞,服務端收到客戶端的請求時,會啟動一個線程處理,「交互」會阻塞直到整個流程結束;

這種模式如果在高并發且流程復雜耗時的場景下,客戶端的請求響應會存在嚴重的性能問題,并且占用過多資源;

2、參考案例

【服務端】啟動ServerSocket接收客戶端的請求,經過一系列邏輯之后,向客戶端發送消息,注意這里線程的10秒休眠;

public class SocketServer01 { public static void main(String[] args) throws Exception { // 1、創建Socket服務端 ServerSocket serverSocket = new ServerSocket(8080); // 2、方法阻塞等待,直到有客戶端連接 Socket socket = serverSocket.accept(); // 3、輸入流,輸出流 InputStream inStream = socket.getInputStream(); OutputStream outStream = socket.getOutputStream(); // 4、數據接收和響應 int readLen = 0; byte[] buf = new byte[1024]; if ((readLen=inStream.read(buf)) != -1){ // 接收數據 String readVar = new String(buf, 0, readLen) ; System.out.println("readVar======="+readVar); } // 響應數據 Thread.sleep(10000); outStream.write("sever-8080-write;".getBytes()); // 5、資源關閉 IoClose.ioClose(outStream,inStream,socket,serverSocket); }}

【客戶端】Socket連接,先向ServerSocket發送請求,再接收其響應,由于Server端模擬耗時,Client處于長時間阻塞狀態;

public class SocketClient01 { public static void main(String[] args) throws Exception { // 1、創建Socket客戶端 Socket socket = new Socket(InetAddress.getLocalHost(), 8080); // 2、輸入流,輸出流 OutputStream outStream = socket.getOutputStream(); InputStream inStream = socket.getInputStream(); // 3、數據發送和響應接收 // 發送數據 outStream.write("client-hello".getBytes()); // 接收數據 int readLen = 0; byte[] buf = new byte[1024]; if ((readLen=inStream.read(buf)) != -1){ String readVar = new String(buf, 0, readLen) ; System.out.println("readVar======="+readVar); } // 4、資源關閉 IoClose.ioClose(inStream,outStream,socket); }}三、同步非阻塞1、模型圖解

NIO即同步非阻塞,服務端可以實現一個線程,處理多個客戶端請求連接,服務端的并發能力得到極大的提升;

這種模式下客戶端的請求連接都會注冊到Selector多路復用器上,多路復用器會進行輪詢,對請求連接的IO流進行處理;

2、參考案例

【服務端】單線程可以處理多個客戶端請求,通過輪詢多路復用器查看是否有IO請求;

public class SocketServer01 { public static void main(String[] args) throws Exception { try { //啟動服務開啟監聽 ServerSocketChannel socketChannel = ServerSocketChannel.open(); socketChannel.socket().bind(new InetSocketAddress("127.0.0.1", 8989)); // 設置非阻塞,接受客戶端 socketChannel.configureBlocking(false); // 打開多路復用器 Selector selector = Selector.open(); // 服務端Socket注冊到多路復用器,指定興趣事件 socketChannel.register(selector, SelectionKey.OP_ACCEPT); // 多路復用器輪詢 ByteBuffer buffer = ByteBuffer.allocateDirect(1024); while (selector.select() > 0){ Set selectionKeys = selector.selectedKeys(); Iterator selectionKeyIter = selectionKeys.iterator(); while (selectionKeyIter.hasNext()){ SelectionKey selectionKey = selectionKeyIter.next() ; selectionKeyIter.remove(); if(selectionKey.isAcceptable()) { // 接受新的連接 SocketChannel client = socketChannel.accept(); // 設置讀非阻塞 client.configureBlocking(false); // 注冊到多路復用器 client.register(selector, SelectionKey.OP_READ); } else if (selectionKey.isReadable()) { // 通道可讀 SocketChannel client = (SocketChannel) selectionKey.channel(); int len = client.read(buffer); if (len > 0){ buffer.flip(); byte[] readArr = new byte[buffer.limit()]; buffer.get(readArr); System.out.println(client.socket().getPort() + "端口數據:" + new String(readArr)); buffer.clear(); } } } } } catch (Exception e) { e.printStackTrace(); } }}

【客戶端】每隔3秒持續的向通道內寫數據,服務端通過輪詢多路復用器,持續的讀取數據;

public class SocketClient01 { public static void main(String[] args) throws Exception { try { // 連接服務端 SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress("127.0.0.1", 8989)); ByteBuffer writeBuffer = ByteBuffer.allocate(1024); String conVar = "client-hello"; writeBuffer.put(conVar.getBytes()); writeBuffer.flip(); // 每隔3S發送一次數據 while (true) { Thread.sleep(3000); writeBuffer.rewind(); socketChannel.write(writeBuffer); writeBuffer.clear(); } } catch (Exception e) { e.printStackTrace(); } }}四、異步非阻塞1、模型圖解

AIO即異步非阻塞,對于通道內數據的「讀」和「寫」動作,都是采用異步的模式,對于性能的提升是巨大的;

這與常規的第三方對接模式很相似,本地服務在請求第三方服務時,請求過程耗時很大,會異步執行,第三方第一次回調,確認請求可以被執行;第二次回調則是推送處理結果,這種思想在處理復雜問題時,可以很大程度的提高性能,節省資源:

2、參考案例

【服務端】各種「accept」、「read」、「write」動作是異步,通過Future來獲取計算的結果;

public class SocketServer01 { public static void main(String[] args) throws Exception { // 啟動服務開啟監聽 AsynchronousServerSocketChannel socketChannel = AsynchronousServerSocketChannel.open() ; socketChannel.bind(new InetSocketAddress("127.0.0.1", 8989)); // 指定30秒內獲取客戶端連接,否則超時 Future acceptFuture = socketChannel.accept(); AsynchronousSocketChannel asyChannel = acceptFuture.get(30, TimeUnit.SECONDS); if (asyChannel != null && asyChannel.isOpen()){ // 讀數據 ByteBuffer inBuffer = ByteBuffer.allocate(1024); Future readResult = asyChannel.read(inBuffer); readResult.get(); System.out.println("read:"+new String(inBuffer.array())); // 寫數據 inBuffer.flip(); Future writeResult = asyChannel.write(ByteBuffer.wrap("server-hello".getBytes())); writeResult.get(); } // 關閉資源 asyChannel.close(); }}

【客戶端】相關「connect」、「read」、「write」方法調用是異步的,通過Future來獲取計算的結果;

public class SocketClient01 { public static void main(String[] args) throws Exception { // 連接服務端 AsynchronousSocketChannel socketChannel = AsynchronousSocketChannel.open(); Future result = socketChannel.connect(new InetSocketAddress("127.0.0.1", 8989)); result.get(); // 寫數據 String conVar = "client-hello"; ByteBuffer reqBuffer = ByteBuffer.wrap(conVar.getBytes()); Future writeFuture = socketChannel.write(reqBuffer); writeFuture.get(); // 讀數據 ByteBuffer inBuffer = ByteBuffer.allocate(1024); Future readFuture = socketChannel.read(inBuffer); readFuture.get(); System.out.println("read:"+new String(inBuffer.array())); // 關閉資源 socketChannel.close(); }}五、Reactor模型1、模型圖解

這部分內容,可以參考「Doug Lea的《IO》」文檔,查看更多細節;

1.1 Reactor設計原理

Reactor模式基于事件驅動設計,也稱為「反應器」模式或者「分發者」模式;服務端收到多個客戶端請求后,會將請求分派給對應的線程處理;

Reactor:負責事件的監聽和分發;Handler:負責處理事件,核心邏輯「read讀」、「decode解碼」、「compute業務計算」、「encode編碼」、「send應答數據」;

1.2 單Reactor單線程

【1】Reactor線程通過select監聽客戶端的請求事件,收到事件后通過Dispatch進行分發;

【2】如果是建立連接請求事件,Acceptor通過「accept」方法獲取連接,并創建一個Handler對象來處理后續業務;

【3】如果不是連接請求事件,則Reactor會將該事件交由當前連接的Handler來處理;

【4】在Handler中,會完成相應的業務流程;

這種模式將所有邏輯「連接、讀寫、業務」放在一個線程中處理,避免多線程的通信,資源競爭等問題,但是存在明顯的并發和性能問題;

1.3 單Reactor多線程

【1】Reactor線程通過select監聽客戶端的請求事件,收到事件后通過Dispatch進行分發;

【2】如果是建立連接請求事件,Acceptor通過「accept」方法獲取連接,并創建一個Handler對象來處理后續業務;

【3】如果不是連接請求事件,則Reactor會將該事件交由當前連接的Handler來處理;

【4】在Handler中,只負責事件響應不處理具體業務,將數據發送給Worker線程池來處理;

【5】Worker線程池會分配具體的線程來處理業務,最后把結果返回給Handler做響應;

這種模式將業務從Reactor單線程分離處理,可以讓其更專注于事件的分發和調度,Handler使用多線程也充分的利用cpu的處理能力,導致邏輯變的更加復雜,Reactor單線程依舊存在高并發的性能問題;

1.4 主從Reactor多線程

【1】 MainReactor主線程通過select監聽客戶端的請求事件,收到事件后通過Dispatch進行分發;

【2】如果是建立連接請求事件,Acceptor通過「accept」方法獲取連接,之后MainReactor將連接分配給SubReactor;

【3】如果不是連接請求事件,則MainReactor將連接分配給SubReactor,SubReactor調用當前連接的Handler來處理;

【4】在Handler中,只負責事件響應不處理具體業務,將數據發送給Worker線程池來處理;

【5】Worker線程池會分配具體的線程來處理業務,最后把結果返回給Handler做響應;

這種模式Reactor線程分工明確,MainReactor負責接收新的請求連接,SubReactor負責后續的交互業務,適應于高并發的處理場景,是Netty組件通信框架的所采用的模式;

2、參考案例

【服務端】提供兩個EventLoopGroup,「ParentGroup」主要是用來接收客戶端的請求連接,真正的處理是轉交給「ChildGroup」執行,即Reactor多線程模型;

@Slf4jpublic class NettyServer { public static void main(String[] args) { // EventLoop組,處理事件和IO EventLoopGroup parentGroup = new NioEventLoopGroup(); EventLoopGroup childGroup = new NioEventLoopGroup(); try { // 服務端啟動引導類 ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(parentGroup, childGroup) .channel(NioServerSocketChannel.class).childHandler(new ServerChannelInit()); // 異步IO的結果 ChannelFuture channelFuture = serverBootstrap.bind(8989).sync(); channelFuture.channel().closeFuture().sync(); } catch (Exception e){ e.printStackTrace(); } finally { parentGroup.shutdownGracefully(); childGroup.shutdownGracefully(); } }}class ServerChannelInit extends ChannelInitializer { @Override protected void initChannel(SocketChannel socketChannel) { // 獲取管道 ChannelPipeline pipeline = socketChannel.pipeline(); // 編碼、解碼器 pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); // 添加自定義的handler pipeline.addLast("serverHandler", new ServerHandler()); }}class ServerHandler extends ChannelInboundHandlerAdapter { /** * 通道讀和寫 */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("Server-Msg【"+msg+"】"); TimeUnit.MILLISECONDS.sleep(2000); String nowTime = DateTime.now().toString(DatePattern.NORM_DATETIME_PATTERN) ; ctx.channel().writeAndFlush("hello-client;time:" + nowTime); ctx.fireChannelActive(); } @Override public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}

【客戶端】通過Bootstrap類,與服務器建立連接,服務端通過ServerBootstrap啟動服務,綁定在8989端口,然后服務端和客戶端進行通信;

public class NettyClient { public static void main(String[] args) { // EventLoop處理事件和IO NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup(); try { // 客戶端通道引導 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(eventLoopGroup) .channel(NioSocketChannel.class).handler(new ClientChannelInit()); // 異步IO的結果 ChannelFuture channelFuture = bootstrap.connect("localhost", 8989).sync(); channelFuture.channel().closeFuture().sync(); } catch (Exception e){ e.printStackTrace(); } finally { eventLoopGroup.shutdownGracefully(); } }}class ClientChannelInit extends ChannelInitializer { @Override protected void initChannel(SocketChannel socketChannel) { // 獲取管道 ChannelPipeline pipeline = socketChannel.pipeline(); // 編碼、解碼器 pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); // 添加自定義的handler pipeline.addLast("clientHandler", new ClientHandler()); }}class ClientHandler extends ChannelInboundHandlerAdapter { /** * 通道讀和寫 */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("Client-Msg【"+msg+"】"); TimeUnit.MILLISECONDS.sleep(2000); String nowTime = DateTime.now().toString(DatePattern.NORM_DATETIME_PATTERN) ; ctx.channel().writeAndFlush("hello-server;time:" + nowTime); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.channel().writeAndFlush("channel...active"); } @Override public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}六、參考源碼

編程文檔:https://gitee.com/cicadasmile/butte-java-note應用倉庫:https://gitee.com/cicadasmile/butte-flyer-parent

關鍵詞:

上一篇:

下一篇:

X 關閉

X 關閉

久久国产精品一区二区三区四区,久色婷婷小香蕉久久,国产日韩欧美在线播放不卡,另类av一区二区
欧美va天堂va视频va在线| 亚洲国产另类 国产精品国产免费| 宅男精品视频| 夜夜躁日日躁狠狠久久88av| 欧美特黄a级高清免费大片a级| 亚洲电影免费观看高清完整版| 在线观看日韩www视频免费| 亚洲人成在线播放| 欧美日韩在线免费| 亚洲精品一区二区三| 黄色成人小视频| 欧美人与性禽动交情品| 亚洲高清视频在线| 国产精品视频1区| 欧美成年人视频| 国产一区二区三区在线免费观看| 国产精品白丝jk黑袜喷水| 性欧美大战久久久久久久免费观看| 欧美三级午夜理伦三级中文幕| 亚洲第一区在线| 麻豆成人综合网| 噜噜噜久久亚洲精品国产品小说| 久久超碰97人人做人人爱| 欧美国产综合一区二区| 亚洲伦理中文字幕| 国产在线播精品第三| 欧美日本久久| 亚洲精品综合久久中文字幕| 欧美视频在线观看视频极品| 欧美a级大片| 国产精品久久网| 亚洲欧美怡红院| 亚洲视频 欧洲视频| 欧美一区二区三区电影在线观看| 欧美大片在线观看| 国产精品国产自产拍高清av| av成人免费| 亚洲精品社区| 亚洲制服av| 中国成人亚色综合网站| 国产一区二区三区高清在线观看| 国产精品日韩一区| 国产精品理论片在线观看| 亚洲欧洲一区二区三区久久| 中日韩美女免费视频网址在线观看| 久久婷婷激情| 99re6这里只有精品视频在线观看| 国产日韩精品综合网站| 精品av久久久久电影| 欧美性猛交一区二区三区精品| 亚洲一区二区三区四区五区午夜| 免费成人av在线| 欧美日韩天堂| 亚洲美女av电影| 国产日韩欧美一二三区| 久久久精品国产免费观看同学| 欧美丝袜第一区| 一本色道久久综合亚洲精品不| 亚洲毛片一区二区| 麻豆精品一区二区综合av| 国产亚洲精品久久久久动| 国产精品视频男人的天堂| 欧美中文在线免费| 亚洲日本无吗高清不卡| 一本一本久久a久久精品综合麻豆| 久久夜色撩人精品| 亚洲视频999| 一本色道久久综合狠狠躁篇怎么玩| 欧美少妇一区| 亚洲欧美成人网| 性欧美长视频| 国产亚洲精品久| 男女av一区三区二区色多| 欧美激情综合色综合啪啪| 国产欧美日韩视频一区二区| 久久精品国产999大香线蕉| 亚洲免费观看高清完整版在线观看熊| 美女免费视频一区| 亚洲人成人一区二区三区| 欧美日韩调教| 一区二区三区高清在线观看| 亚洲视频你懂的| 国产色婷婷国产综合在线理论片a| 国产精品亚洲第一区在线暖暖韩国| 激情五月综合色婷婷一区二区| 欧美激情一区二区三区四区| 亚洲夫妻自拍| 欧美全黄视频| 国产精品视区| 亚洲欧美激情视频| 亚洲国产欧美在线| 国产一区二区三区不卡在线观看| 久久久免费精品视频| 久久精品91久久久久久再现| 久久久久久久网站| 国产欧美91| 欧美日韩国产综合新一区| 国产日韩精品一区二区三区| 亚洲一区影音先锋| 亚洲桃花岛网站| 一区二区三区产品免费精品久久75| 国产精品美女| 欧美在线观看www| 99re6这里只有精品| 久久人人爽人人爽爽久久| 亚洲午夜一区二区三区| 亚洲第一视频| 亚洲国产高清aⅴ视频| 99精品国产高清一区二区| 午夜视频一区| 久久久久久9| 欧美大尺度在线观看| 在线观看成人av| 欧美私人啪啪vps| 欧美伊人久久| 欧美一区二区三区在线| 亚洲高清影视| 国产日韩欧美91| 国产综合香蕉五月婷在线| 欧美精品aa| 亚洲国产精品一区二区第一页| 欧美一区二区日韩一区二区| 欧美a级理论片| 亚洲精品国产无天堂网2021| 午夜在线电影亚洲一区| 亚洲精选一区二区| 99热这里只有成人精品国产| 精品9999| 国产精品免费电影| 欧美日韩免费观看一区三区| 久久精品日韩一区二区三区| 国产精品自拍在线| 亚洲综合电影一区二区三区| 国产精品看片资源| 精品成人国产在线观看男人呻吟| 亚洲欧美成人在线| 夜夜爽夜夜爽精品视频| 最新国产精品拍自在线播放| 国产精品久久久一本精品| 麻豆91精品| 亚洲一区二区三区色| 欧美日韩黄色大片| 欧美综合国产| 久久成人这里只有精品| 欧美视频中文字幕| 国产精品一区二区三区成人| 久久精彩视频| 亚洲毛片一区二区| 亚洲尤物精选| 亚洲欧美卡通另类91av| 亚洲视频综合| 国内不卡一区二区三区| 欧美一区91| 亚洲第一中文字幕在线观看| 久久久国产精彩视频美女艺术照福利| 亚洲激情国产精品| 国内精品伊人久久久久av一坑| 国产精品一区二区三区乱码| 久久精品一区蜜桃臀影院| 亚洲永久免费| 99热在线精品观看| 欲色影视综合吧| 日韩视频免费在线| 国产一区二区成人| 久久婷婷国产综合精品青草| 欧美日韩精品综合在线| 在线观看欧美| 久久精品国产亚洲aⅴ| 亚洲午夜精品久久久久久app| 久久视频在线视频| 亚洲第一色中文字幕| 亚洲精品一区在线观看香蕉| 国产午夜精品理论片a级大结局| 国内精品**久久毛片app| 久久手机精品视频| 国产精品裸体一区二区三区| 久热爱精品视频线路一| 性感少妇一区| 久久九九热免费视频| 中文精品一区二区三区| 欧美大片在线影院| 黑人一区二区三区四区五区| 亚洲一区免费在线观看| 国产精品欧美经典| 亚洲一区二区三区乱码aⅴ蜜桃女| 午夜精品福利电影| 亚洲欧美日韩国产成人精品影院| 国产一区二区三区精品欧美日韩一区二区三区| 亚洲国产精品小视频| 午夜日韩在线观看| 久久在线免费| 欧美日韩亚洲高清一区二区| 久久国产欧美精品| 久久精品99无色码中文字幕| 欧美精品久久久久久久久久| 亚洲国产精品第一区二区| 国产精品jizz在线观看美国| 亚洲欧美日韩网| 欧美一区二区高清| 亚洲伊人一本大道中文字幕|