java NIO(顺道解释一下 BIO,伪异步IO,AIO,netty框架)

NIO : 异步非阻塞IO

介绍一下我了解Dao的NIO的基础知识: 非阻塞IO
(1) Buffer (缓冲区)
(2) Channel 通道 负责数据传输
(3) selector 选择器

举一个生活中的例子:就是高铁 channel就是我们的铁路连接北京和上海 然后Buffer就是和谐号列车 selector就是我们的铁路调度系统 我们人就是数据 我们需要进入buffer 然后通过channel在selector 的调度下进行传输.

首先buffer 顾名思义 缓冲 他的作用可以想象成数据传输的媒介 我们可以将一个buffer 写到一个channel 也可以从channel读取一个buffer 一般实例化的时候都需要设定大小
获取的方法有两种: 1.通过seletionKey获取
2.通过ByteBuffer.allocate(size)
ByteBuffer:
就是一个缓冲区类型的的东西:

有两种模式一种是 写模式 一种是 读模式!
之间用.filp()方法进行切换 这个方法的作用就是操作position, limit指针的内容
.compact() 方法的作用是 将position 和 limit之间的东西 移到最开始 然后position指向
插入之后的位置
clear() limit = 最后 position = 0 这个没有什么好说的
实例化 ByteBuffer.allocate();

然后是channel 经常使用的channel 是 FileChannel , SocketChannel , ServeSocketChannel
这三个 他可以执行写操作和读操作 当然他的媒介是buffer

最后selector 中有两个属性很重要:
keys selectionKeys
key: 注册到selector 中的channel 的数目
selelctionKey; 需要执行的Channel

来个例子:
public class Client {
public static void main(String[] args) throws IOException {
ByteBuffer bb = ByteBuffer. allocate ( 1024 );
SocketChannel socketChannel = null ;
try {
socketChannel = SocketChannel. open ();
socketChannel.configureBlocking( false );
socketChannel.connect( new InetSocketAddress( "127.0.0.1" , 8882 ));
if (socketChannel.finishConnect()) {
String msg = "hello" ;
bb.put(msg.getBytes());
bb.flip();
socketChannel.write(bb);
sleep ( 4000 ); //这个是必须的 如果不加 他就会直接执行完成 当然也可以通过 死循环来实现

bb.clear();
int n = socketChannel.read(bb);
while (n > 0 ) {
bb.flip();
while (bb.hasRemaining()) {
System. out .print(( char ) bb.get());
}
n = socketChannel.read(bb);
}
sleep ( 4000 ); //再测试一波写入


bb.clear();
bb.put(msg.getBytes());
bb.flip();
socketChannel.write(bb);
sleep ( 4000 ); //这个是必须的 如果不加 他就会直接执行完成 当然也可以通过 死循环来实现

bb.clear();
n = socketChannel.read(bb);
while (n > 0 ) {
bb.flip();
while (bb.hasRemaining()) {
System. out .print(( char ) bb.get());
}
n = socketChannel.read(bb);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (socketChannel != null ) {
socketChannel.close();
}
}
}
}

public class Server {
public static void main(String[] args) {
try {
Selector selector = Selector. open ();
ServerSocketChannel ssc = ServerSocketChannel. open ();
ssc.configureBlocking( false );
ssc.socket().bind( new InetSocketAddress( 8882 ));
ssc.register(selector, SelectionKey. OP_ACCEPT );
while ( true ) {
sleep ( 1000 );
if (selector.selectNow() == 0 ) {
System. out .println( "==" );
continue ;
}
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey sk = it.next();
if (sk.isAcceptable()) {
handleAccept (sk);
System. out .println( "accept" );
} else if (sk.isReadable()) {
System. out .println( "read" );
handleReader (sk);
} else if (sk.isWritable()) {
handleWrite (sk);
System. out .println( "write" );
} else if (sk.isConnectable()) {
System. out .println( "is connected!" );
}
it.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void handleReader(SelectionKey sk) {
SocketChannel sc = (SocketChannel) sk.channel();
ByteBuffer bf = (ByteBuffer) sk.attachment();
try {
long n = sc.read(bf);
while (n > 0 ) {
bf.flip();
while (bf.hasRemaining()) {
System. out .print(( char ) bf.get());
}
System. out .println();
bf.compact();
n = sc.read(bf);
}
sc.register(sk.selector(), SelectionKey. OP_WRITE , ByteBuffer. allocate ( 1024 ));

} catch (IOException e) {
e.printStackTrace();
}
}
public static void handleAccept(SelectionKey sk) {
ServerSocketChannel ssc = (ServerSocketChannel) sk.channel();
try {
SocketChannel sc = ssc.accept();
sc.configureBlocking( false );
sc.register(sk.selector(), SelectionKey. OP_READ , ByteBuffer. allocate ( 1024 ));
} catch (IOException e) {
e.printStackTrace();
}
}
public static void handleWrite(SelectionKey sk) {
String info = "response:" ;
SocketChannel sc = (SocketChannel) sk.channel();
ByteBuffer bb = ByteBuffer. allocate ( 1024 );
bb.put(info.getBytes());
bb.flip();
try {
while (bb.hasRemaining()) {
System. out .print( "response:" );
sc.write(bb);
}
System. out .println();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
sc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


BIO: 阻塞IO 面向流 一个连接对应一个线程
伪异步IO: 这个是为了解决上头BIO(也就是传统的CS模型的弊端, 一个连接一个线程的弊端就是系统的开销大) 而伪异步IO 采用线程池的方式代替为每一个连接创建线程, 而是从线程池中取空闲的线程. 这样的方式优化了传统的C/S模型 但是还是不能解决高并发条件下的线程大量等待.
NIO: 也就是上面讲的 非阻塞IO, 可以解决高并发条件下线程等待的问题
AIO: 异步IO 这个是NIO的进化版本 这个相比较与NIO 他最大的特征就是事件驱动, 有两个函数completed 和 failed 通过监控事件的结果,成功/失败 来调用返回的结果, 以下加粗部分就是AIO的核心部分., 其实总结一下 就是套接字的每一个操作都伴随着事件. 如
accept(null, new CompletionHandler<AsynchronousSocketChannel,Object>(){}), connect(), read(), write()等 都可以添加一个事件, 具体的可以看一下源码.

public class AIOEchoServer {
public final static int PORT = 8001;
public final static String IP = "127.0.0.1";
private AsynchronousServerSocketChannel server = null;
public AIOEchoServer(){
try {
//同样是利用工厂方法产生一个通道,异步通道 AsynchronousServerSocketChannel
server = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(IP,PORT));
} catch (IOException e) {
e.printStackTrace();
}
}
//使用这个通道(server)来进行客户端的接收和处理
public void start(){
System.out.println("Server listen on "+PORT);
//注册事件和事件完成后的处理器,这个CompletionHandler就是事件完成后的处理器
server.accept(null,new CompletionHandler<AsynchronousSocketChannel,Object>(){
final ByteBuffer buffer = ByteBuffer.allocate(1024);
@Override
public void completed(AsynchronousSocketChannel result,Object attachment) {
System.out.println(Thread.currentThread().getName());
Future<Integer> writeResult = null;
try{
buffer.clear();
result.read(buffer).get(100,TimeUnit.SECONDS);
System.out.println("In server: "+ new String(buffer.array()));
//将数据写回客户端
buffer.flip();
writeResult = result.write(buffer);
}catch(InterruptedException | ExecutionException | TimeoutException e){
e.printStackTrace();
}finally{
server.accept(null,this);
try {
writeResult.get();
result.close();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void failed(Throwable exc, Object attachment) {
System.out.println("failed:"+exc);
}
});
}
public static void main(String[] args) {
new AIOEchoServer().start();
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值