您的位置:首页 > 编程语言 > Java开发

Java Netty 学习笔记(一)初识Netty

2017-05-20 16:25 288 查看
记得前段时间面试,有些主攻java的公司总会问“你对网络编程比较熟,那java的AIO BIO NIO”知道么,答曰,确实对java不熟。在陈硕muduo中多次提到与netty都是用的
one loop per thread
,于是找了一个做Java后台的大佬借了一本Netty权威指南,开始学习。

代码:https://github.com/NearXdu/NettyLearn

1. BIO

B阻塞,传统的同步阻塞式IO,在UNP中,这种IO是 
one connection per thread/process
,在Java中似乎Listen Fd 和 Accept Fd 分别有各自的封装
ServerSocket
Socket
.编程框架也是比较简单的:

server = new ServerSocket(port);
while (true){
socket = server.accept();
new Thread(new ServerHandler(socket)).start();
}
//
ServerHandler implements Runnable {
private Socket socket;
public void run(){
//...
}
}


主线程在loop中阻塞在
accept
调用,当新连接的到来的时候,将connfd扔进handle线程中,主线程继续等待连接.

2.伪异步

不用每次的创建线程,因为这样开销很大,用任务队列+线程池的方式,实现伪异步。

具体:

将Socket封装成一个Task,该Task实现Runnable接口,投递到任务队列中,后端的线程池进行处理。线程池中的线程有限,当任务数比较多时,将阻塞在任务队列里面(blocking queue),同样当任务队列为空时,线程池的线程也将挂起。这些java都封装好了,用起来还是很方便的:

executor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
maxPoolSize,//线程池大小
120L,
TimeUnit.SECONDS,//最大空闲实现
new ArrayBlockingQueue<java.lang.Runnable>(queueSize));//blocking Queue Size

while(true)
{
socket=server.accept();
executor.execute(new task(socket));
}


3.NIO编程

也就是Reactor,在netty中,有几个重要的组件:
Buffer
读写缓冲,
Channel
对描述符的封装,
Selector
多路复用选择器。

使用NIO编程的步骤如下:

//监听套接字
ServerSocketChannel acceptorSvr=ServerSocketChannel.open();
bind;
acceptorSvr.configureBlocking(false);
//创建selecto并启动线程
Selector selector = Selector.open();
new Thread(new ReactorTask()).start();
//将监听套接字注册到selector上
SelectionKey key=acceptorSvr.register(selector,OP_ACCEPT,ioHandler);
//在Reactor线程中轮询
int num=selector.select();
Set selectedKey=selector.selectedKeys();
Iterator it = selectdKey.iterator();
while(it.hasNext()){
SelectionKey key = (SelectionKey)it.next();
//...
}
//accept新连接
SocketChannel channel= svrChannel.accept();
//为已连接套接字注册IO事件
SelectionKey key=socketChannel.register(selector,SelectionKey.OP_READ,ioHandler)


4.AIO

异步编程,有点类似boost.asio,每次需要注册完成回调,并在完成回调中调用异步操作来驱动,最终形

成一个循环。需要程序员实现一个CompletionHandler接口,相比同步Selector,AIO是真正的异步调用

例如

public class AcceptCompletionHandler implements
CompletionHandler<AsynchronousSocketChannel, AsyncTimeServerHandler> {
@Override
public void completed(AsynchronousSocketChannel asynchronousSocketChannel, AsyncTimeServerHandler asyncTimeServerHandler) {
asyncTimeServerHandler.asynchronousServerSocketChannel.accept();
ByteBuffer buffer = ByteBuffer.allocate(1024);
asynchronousSocketChannel.read(buffer,buffer,new ReadCompletionHandler(asynchronousSocketChannel));

}

@Override
public void failed(Throwable throwable, AsyncTimeServerHandler asyncTimeServerHandler) {
throwable.printStackTrace();
asyncTimeServerHandler.latch.countDown();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: