java io nio pio_Netty之BIO(同步阻塞IO)、PIO(偽異步阻塞IO)、NIO(異步非阻塞IO)、AIO(異步非阻塞IO)、Netty...

本文介绍了Java中的三种IO模型:BIO(同步阻塞)、PIO(伪异步阻塞)和NIO(异步非阻塞),并详细解释了它们的工作原理和优缺点。特别提到了在高并发场景下,NIO通过多路复用器Selector优化了性能。此外,还探讨了AIO(异步非阻塞)作为NIO的进一步发展。最后,通过示例展示了如何使用Netty框架创建一个简单的服务器和客户端,强调了Netty简化NIO编程模型的特性。
摘要由CSDN通过智能技术生成

學習書籍:Netty權威指南

多種IO方式的比較:

1、BIO(同步阻塞IO)

使用ServerSocket綁定IP地址和監聽端口,客戶端發起連接,通過三次握手建立連接,用socket來進行通信,通過輸入輸出流的方式來進行同步阻塞的通信

每次客戶端發起連接請求,都會啟動一個線程

線程數量:客戶端並發訪問數為1:1,由於線程是JAVA虛擬機中非常寶貴的資源,一旦線程數急劇增加,系統性能會急劇下降,導致線程棧溢出,創建新的線程失敗,並最終導致宕機

所以在JDK1.4之前,人們想到了一種方法,即PIO方式

2、PIO(偽異步阻塞IO)

使用線程池來處理客戶端的請求

客戶端個數:線程池最大線程數=M:N,其中M遠大於N

在read和write的時候,還是IO阻塞的,只是把每個線程交由線程池來控制管理

3、NIO(異步阻塞IO)

用NIO方式處理IO

使用多路復用器Selector來輪詢每個通道Channel,當通道中有事件時就通知處理,不會阻塞

使用相當復雜

4、AIO(真正的異步非阻塞IO)

NIO2.0引入了新的異步通道的概念,不需要使用多路復用器(Selector)對注冊通道進行輪詢即可實現異步讀寫,從而簡化了NIO編程模型

使用Netty框架進行編程步驟

1、構建事件處理池

2、使用引導程序關聯事件處理池、通道、事件處理器

3、綁定端口服務

4、等待操作完成

5、關閉事件處理池

幾種IO的功能和特性對比

527b181841ee988d9cc2660448f39e9b.jpe

按照書上的例子碼了一遍:

服務端:

import io.netty.bootstrap.ServerBootstrap;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelOption;

import io.netty.channel.EventLoopGroup;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.SocketChannel;

import io.netty.channel.socket.nio.NioServerSocketChannel;

public class NettyServer {

public void bind(int port) throws Exception {

EventLoopGroup bossGroup = new NioEventLoopGroup();

EventLoopGroup workGroup = new NioEventLoopGroup();

try {

ServerBootstrap b = new ServerBootstrap();

b.group(bossGroup, workGroup).channel(NioServerSocketChannel.class)

.option(ChannelOption.SO_BACKLOG, 1024)

.childHandler(new ChildChannelHandler());

// 綁定端口,同步等待成功

ChannelFuture f = b.bind(port).sync();

// 等待服務端監聽端口關閉

f.channel().closeFuture().sync();

} catch (Exception e) {

// TODO: handle exception

} finally {

// 優雅退出,釋放線程池資源

bossGroup.shutdownGracefully();

workGroup.shutdownGracefully();

}

}

private class ChildChannelHandler extends ChannelInitializer {

@Override

protected void initChannel(SocketChannel ch) throws Exception {

ch.pipeline().addLast(new NettyServerHandle());

}

}

public static void main(String[] args) throws Exception {

int port = 8080;

if (args != null && args.length > 0) {

try {

port = Integer.valueOf(args[0]);

} catch (Exception e) {

e.printStackTrace();

}

}

new NettyServer().bind(port);

}

}

服務端處理器:

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelHandlerAdapter;

import io.netty.channel.ChannelHandlerContext;

public class NettyServerHandle extends ChannelHandlerAdapter {

public void channelRead(ChannelHandlerContext ctx, Object msg)

throws Exception {

ByteBuf buf = (ByteBuf) msg;

byte[] req = new byte[buf.readableBytes()];

buf.readBytes(req);

String body = new String(req, "UTF-8");

System.out.println("The time server receive order:" + body);

String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new java.util.Date(

System.currentTimeMillis()).toString() : "BAD ORDER";

ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());

ctx.write(resp);

}

public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

ctx.flush();

}

public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {

ctx.close();

}

}

客戶端:

import io.netty.bootstrap.Bootstrap;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelOption;

import io.netty.channel.EventLoopGroup;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.SocketChannel;

import io.netty.channel.socket.nio.NioSocketChannel;

public class NettyClient {

public void connect(int port, String host) throws Exception {

// 1、創建線程池

EventLoopGroup group = new NioEventLoopGroup();

try {

// 2、使用引導器關聯線程池、通道、通達處理器、設置執行參數

Bootstrap b = new Bootstrap();

b.group(group).channel(NioSocketChannel.class)

.option(ChannelOption.TCP_NODELAY, true)

.handler(new ChannelInitializer() {

@Override

protected void initChannel(SocketChannel ch)

throws Exception {

ch.pipeline().addLast(new NettyClientHandle());

}

});

// 發起異步連接操作 3、綁定端口同步操作

ChannelFuture f = b.connect(host, port).sync();

// 4、監聽端口關閉

f.channel().closeFuture().sync();

} catch (Exception e) {

// TODO: handle exception

} finally {

// 優雅退出,釋放NIO線程組 5、釋放資源

group.shutdownGracefully();

}

}

public static void main(String[] args) throws Exception {

int port = 8080;

if (args != null && args.length > 0) {

try {

port = Integer.valueOf(args[0]);

} catch (Exception e) {

e.printStackTrace();

}

}

new NettyClient().connect(port, "127.0.0.1");

}

}

客戶端處理器:

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelHandlerAdapter;

import io.netty.channel.ChannelHandlerContext;

import java.util.logging.Logger;

public class NettyClientHandle extends ChannelHandlerAdapter {

private static final Logger logger = Logger

.getLogger(NettyClientHandle.class.getName());

private final ByteBuf firstMessage;

public NettyClientHandle() {

byte[] req = "QUERY TIME ORDER".getBytes();

firstMessage = Unpooled.buffer(req.length);

firstMessage.writeBytes(req);

}

public void channelActive(ChannelHandlerContext ctx) {

ctx.writeAndFlush(firstMessage);

}

public void channelRead(ChannelHandlerContext ctx, Object msg)

throws Exception {

ByteBuf buf = (ByteBuf) msg;

byte[] req = new byte[buf.readableBytes()];

buf.readBytes(req);

String body = new String(req, "UTF-8");

System.out.println("Now is:" + body);

}

public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {

// 釋放資源

logger.warning("Unexpected exception from downstream:"

+ cause.getMessage());

ctx.close();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值