AIO是在NIO基础上实现的异步非阻塞通信
Windows下提供了IOCP技术,I/O Completion Port,称为I/O完成端口。IOCP是一个消息队列。当监听到客户请求的时候就把请求加到消息队列中。然后已有的线程去逐一处理,处理完成后需要得到反馈的工作线程就会收到通知,然后前去处理。当没有请求加入到消息队列的时候,相应的线程也就处理挂起的状态进行等待。
所以Windows下算是有实际意义上的异步非阻塞
同步异步是消息通信的机制
阻塞非阻塞是事件处理
阻塞:死等着被调用方回信,中间什么不干
非阻塞:没收到被调用方回信时,中间干点别的
同步:一会儿一趟,没有结果就反复问
异步:问完等对方通知反馈
同步阻塞:到服务台反复问讯,死等服务生反馈
同步非阻塞:到服务台反复问询,在等服务生反馈期间玩手机
异步阻塞:到服务台问讯,死等服务生反馈,服务生确认后通知我
异步非阻塞:到服务台问询,问完就玩手机去了,服务生确认后通知我
Linux用epoll进行相关实现
AIO服务端实现
package netty.aio;
/**
- AIO模式服务端实现
- @author zhousjmas@hotmail.com
-
*/
public class AIOSocketServerMain {public static void main(String[] args) {
int port = 9999; AIOSocketServer selector = new AIOSocketServer(port); new Thread(selector).start();
}
}
package netty.aio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.concurrent.CountDownLatch;
/**
- NIO的多路复用器的实现
- @author zhousjmas@hotmail.com
-
*/
public class AIOSocketServer implements Runnable{private int port;
//用于限制一个线程等待其他线程各自执行完毕后再执行。
CountDownLatch countDownLatch;
AsynchronousServerSocketChannel asynchronousServerSocketChannel;//传入端口参数
public AIOSocketServer(int port) {this.port = port; try { asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open(); asynchronousServerSocketChannel.bind(new InetSocketAddress(port)); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }
}
@Override
public void run() {//这里使用countdownlatch是为了把线程阻止住 countDownLatch = new CountDownLatch(1); accept(); try { //多个线程在开始执行任务前首先 coundownlatch.await(), //当主线程调用 countDown() 时,计数器变为0,多个线程同时被唤醒。 countDownLatch.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }
}
private void accept() {
asynchronousServerSocketChannel.accept(this,new AIOHandler());
}
}
package netty.aio;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
public class AIOSocketHandler implements CompletionHandler
private AsynchronousSocketChannel asynchronousSocketChannel;
public AIOSocketHandler(AsynchronousSocketChannel asynchronousSocketChannel) {
if(this.asynchronousSocketChannel==null)
this.asynchronousSocketChannel = asynchronousSocketChannel;
}
@Override
public void completed(Integer result, ByteBuffer buffer) {
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
try {
String info = new String(bytes,"UTF-8");
System.out.println("收到信息:"+info);
sendMessage(new Long(System.currentTimeMillis()).toString());
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void sendMessage(String message) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put(message.getBytes());
buffer.flip();
asynchronousSocketChannel.write(buffer,buffer,new CompletionHandler(){
@Override
public void completed(Integer result, ByteBuffer buffer) {
if(buffer.hasRemaining()) {
asynchronousSocketChannel.write(buffer,buffer,this);
}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
try {
asynchronousSocketChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
try {
asynchronousSocketChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package netty.aio;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
public class AIOHandler implements CompletionHandler
@Override
public void completed(AsynchronousSocketChannel channel, AIOSocketServer handler) {
// TODO Auto-generated method stub
handler.asynchronousServerSocketChannel.accept(handler,this);
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer, buffer, new AIOSocketHandler(channel));
}
@Override
public void failed(Throwable exc, AIOSocketServer handler) {
// TODO Auto-generated method stub
handler.countDownLatch.countDown();
}
}
客户端测试代码
package netty.aio;
public class ClientThreadMain {
public static void main(String[] args) {
String ip = "127.0.0.1";
int port = 9999;
new Thread(new AIOSocketClient(ip,port)).start();
}
}
package netty.aio;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.CountDownLatch;
import io.netty.channel.unix.Buffer;
/**
- AIO模式客户端实现
- @author zhousjmas@hotmail.com
-
*/
public class AIOSocketClient implements CompletionHandler, Runnable{ private AsynchronousSocketChannel asynchronousSocketChannel;
private String ip;
private int port;
private CountDownLatch countDownLatch;public AIOSocketClient(String ip,int port) {
this.ip = ip; this.port = port; //建立通道 try { asynchronousSocketChannel = AsynchronousSocketChannel.open(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
}br/>@Override
public void run() {
// TODO Auto-generated method stub}
@Override
public void completed(Void result, AIOSocketClient attachment) {byte[] bytes = "Hello JAVA AIO WORLD".getBytes(); ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length); byteBuffer.put(bytes); byteBuffer.flip(); asynchronousSocketChannel.write(byteBuffer, byteBuffer, new CompletionHandler
(){ @Override public void completed(Integer result, ByteBuffer buffer) { if(buffer.hasRemaining()) { asynchronousSocketChannel.write(buffer,buffer,this); }else { ByteBuffer reader = ByteBuffer.allocate(1024); asynchronousSocketChannel.read(reader, reader, new CompletionHandler (){ @Override public void completed(Integer result, ByteBuffer buffer) { buffer.flip(); byte[] bytes = new byte[buffer.remaining()]; buffer.get(bytes); String info = ""; try { info = new String(bytes,"UTF-8"); System.out.println("读入信息:"+info); countDownLatch.countDown(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void failed(Throwable exc, ByteBuffer buffer) { // TODO Auto-generated method stub try { asynchronousSocketChannel.close(); countDownLatch.countDown(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } } @Override public void failed(Throwable exc, ByteBuffer attachment) { try { asynchronousSocketChannel.close(); countDownLatch.countDown(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); }
@Override
public void failed(Throwable exc, AIOSocketClient attachment) {
// TODO Auto-generated method stub
try {
asynchronousSocketChannel.close();countDownLatch.countDown(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
}
}
这里用到了很多回调的地方,会稍后补一个回调的小例子进行说明
BIO,简单但不堪重负
NIO,华丽但不完美
所以后边要用Netty