Java BIO, NIO, AIO 简单理解

1, 同步 VS. 异步

比较的是当某种事件发生时调用处理函数的方式,

同步:应用程序主动调用处理函数,

异步:操作系统调用应用程序的处理函数(也叫回调函数),对应用程序而言是被动过程。

 

2, 阻塞 VS. 非阻塞

阻塞:应用程序发起IO请求,IO请求(假设是网络上的IO)会经过网络、网卡、操作系统等,在这个过程中应用程序必须等到操作系统完成IO操作,才能继续后面的事情,因此称为阻塞,

非阻塞:应用程序在发起IO请求后不必等待操作系统完成IO操作,应用程序可以继续做后面的事情,应用程序可以主动查询(轮训)某种IO事件是否完成,并调用相应的处理函数,或者在IO事件发生时操作系统调用应用程序的回调函数。

 

3, BIO,NIO,AIO

 JDK版本  同步and 阻塞 模型类型隐喻
BIO1.0同步阻塞一连接一线程

一个人开了一个餐厅,需要负责迎客(Accept connection)、

等待客户点菜(Read data)、炒菜(处理请求)、

等待客户用餐(Write data)、收银(Close connection),此人在任何时刻

只能服务于一个客户,新来的客户必须等待。

改进型:一人迎客,之后再交由店里空闲的员工独自完成点菜、炒菜、

等待客户用餐、收银等操作,即多线程模式,这在一定程度上能提高性能。

NIO1.4同步非阻塞

一请求一线程,Reactor

一个人开了一个餐厅,负责迎客等所有操作,迎客后让客户点菜,在客户点菜的过程中可以

做其它的操作,并每隔一段时间查看客户是否点菜完毕,如果点菜完毕则开始

炒菜。其它操作类似,如客户用餐,不用等待客户用餐,只需每隔一段时间查看

客户是否用餐完毕,再进行后续操作。

改进型:一个人负责检查是否有某种事件发生,如是否有新客户到来,是否有某个客户点菜

完毕,是否有某个客户用餐完毕等等,多个员工负责处理事件,如某个客户点菜完毕

则让一个空闲的员工来炒菜,如果某个客户用餐完毕,则让一个空闲的员工来收银等等。

由于不用等待客户(即没有IO阻塞),在很大程度上提高了系统系能。

AIO1.7异步非阻塞

一有效请求一线程,Proactor,

需要OS支持,Windows:IOCP,Linux:epoll

 

与NIO类似,只是不用主动查询是否有某种事件发生,而是被告知该事件已发生。如客户

点菜完毕后会主动说“我已经点菜完毕了”,然后让一个空闲的员工来取菜单并炒菜。

AIO是真正意义的异步IO,需要OS支持,在读IO数据时操作系统会将数据读入到应用程序

指定的缓存(ByteByffer)中,应用程序直接使用即可,不像NIO还要应用程序自己读取。

AIO能简化应用程序的编写,因为其只关心有效的请求,将指定的请求绑定到对应的回调函数

中即可,OS会自动调用回调函来处理请求。

 

 

4, BIO代码片段

package com.my.study.io.bio;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server {
	private static final int PORT = 8888;
	private ServerSocket serverSocket = null;

	private ExecutorService service = Executors.newFixedThreadPool(5);

	private void startServer() {
		try {
			serverSocket = new ServerSocket(PORT);
			System.out.println("Server started on port: " + PORT);

			while (true) {
				Socket socket = serverSocket.accept();

				System.out.println("Received a new connection.");

				service.submit(new RequestResolver(socket));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static class RequestResolver implements Runnable {
		private Socket socket;

		public RequestResolver(Socket socket) {
			this.socket = socket;
		}

		public void run() {

			DataInputStream din = null;
			DataOutputStream dout = null;

			try {

				long threadId = Thread.currentThread().getId();

				InputStream in = socket.getInputStream();
				din = new DataInputStream(in);
				String str = din.readUTF();
				System.out.println("Thread: " + threadId + ", read message: "
						+ str);

				OutputStream out = socket.getOutputStream();
				dout = new DataOutputStream(out);
				dout.writeUTF("Response from server.");
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				if (din != null) {
					try {
						din.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}

				if (dout != null) {
					try {
						din.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}

				if (!socket.isClosed()) {
					try {
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	public static void main(String[] args) {
		new Server().startServer();
	}
}


package com.my.study.io.bio;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client {

	private static final int PORT = 8888;

	private static void testSendMessage() {

		Socket socket = null;

		DataInputStream din = null;
		DataOutputStream dout = null;

		try {
			socket = new Socket("127.0.0.1", PORT);

			OutputStream out = socket.getOutputStream();
			dout = new DataOutputStream(out);
			dout.writeUTF("This message is from a client.");

			InputStream in = socket.getInputStream();
			din = new DataInputStream(in);
			String str = din.readUTF();
			System.out.println("Response from server: " + str);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (din != null) {
				try {
					din.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (dout != null) {
				try {
					din.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (!socket.isClosed()) {
				try {
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void main(String[] args) {
		testSendMessage();
	}
}
 
5,NIO代码片段
<pre class="java" name="code">package com.my.study.io.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class Server {
	private static final int PORT = 8888;
	private Selector selector;

	private void startServer() {
		try {
			selector = Selector.open();
			ServerSocketChannel serverSocketChannel = ServerSocketChannel
					.open();
			serverSocketChannel.configureBlocking(false);
			SocketAddress address = new InetSocketAddress(PORT);
			serverSocketChannel.bind(address);
			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

			System.out.println("Server started on port: " + PORT);
			while (true) {
				int selectCode = selector.select(1000);
				if (selectCode == 0) {
					continue;
				}

				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> it = keys.iterator();
				while (it.hasNext()) {
					SelectionKey key = it.next();
					if (key.isAcceptable()) {
						System.out.println("Received a request.");
						serverSocketChannel = (ServerSocketChannel) key
								.channel();
						SocketChannel socketChannel = serverSocketChannel
								.accept();
						socketChannel.configureBlocking(false);
						socketChannel.register(selector, SelectionKey.OP_READ);
					} else if (key.isReadable()) {
						readData(key);
					} else {
						System.out.println("Key is no recognised, key: " + key);
					}
					it.remove();
				}

			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void readData(SelectionKey key) {
		SocketChannel socketChannel = (SocketChannel) key.channel();
		ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
		try {
			socketChannel.read(buffer);
			byte[] bytes = buffer.array();
			String message = new String(bytes).toString();
			System.out.println("Received message from client: " + message);

			socketChannel.write(ByteBuffer.wrap("Response from server."
					.getBytes()));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		new Server().startServer();
	}
}


package com.my.study.io.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class Client {

	private Selector selector;

	public void initClient(String ip, int port) throws IOException {
		SocketChannel channel = SocketChannel.open();
		channel.configureBlocking(false);
		this.selector = Selector.open();
		channel.connect(new InetSocketAddress(ip, port));
		channel.register(selector, SelectionKey.OP_CONNECT);
	}

	public void listen() throws IOException {
		while (true) {
			int selectCode = selector.select(1000);
			if (selectCode == 0) {
				continue;
			}

			Iterator<SelectionKey> it = this.selector.selectedKeys().iterator();
			while (it.hasNext()) {
				SelectionKey key = (SelectionKey) it.next();
				if (key.isConnectable()) {
					SocketChannel channel = (SocketChannel) key.channel();
					if (channel.isConnectionPending()) {
						channel.finishConnect();

					}
					channel.configureBlocking(false);
					channel.register(this.selector, SelectionKey.OP_READ);

					channel.write(ByteBuffer.wrap(new String(
							"Message from a client.").getBytes()));
				} else if (key.isReadable()) {
					readData(key);
				}
				it.remove();
			}
		}
	}

	public void readData(SelectionKey key) throws IOException {
		SocketChannel channel = (SocketChannel) key.channel();
		ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
		channel.read(buffer);
		byte[] data = buffer.array();
		String msg = new String(data).trim();
		System.out.println("Response from server: " + msg);
	}

	public static void main(String[] args) throws IOException {
		Client client = new Client();
		client.initClient("localhost", 8888);
		client.listen();
	}

}

 
6,AIO代码片段
<pre class="java" name="code">package com.my.study.io.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.TimeUnit;

public class Server {
	private static final int PORT = 8888;

	private AsynchronousServerSocketChannel server;

	private void startServer() {
		try {
			server = AsynchronousServerSocketChannel.open().bind(
					new InetSocketAddress(PORT));

			System.out.println("Server started on port: " + PORT);

			server.accept(null,
					new CompletionHandler<AsynchronousSocketChannel, Object>() {
						final ByteBuffer buffer = ByteBuffer
								.allocate(1024 * 1024);

						public void completed(AsynchronousSocketChannel result,
								Object attachment) {
							buffer.clear();
							try {
								result.read(buffer).get(100, TimeUnit.SECONDS);
								buffer.flip();
								String str = new String(buffer.array());
								System.out.println("Received message: " + str);

								result.write(ByteBuffer
										.wrap("Response from server."
												.getBytes()));
							} catch (Exception e) {
								e.printStackTrace();
							} finally {
								try {
									result.close();
									server.accept(null, this);
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}

						public void failed(Throwable exc, Object attachment) {
							System.out.println("Failed: " + exc);
						}
					});
			while (true) {
				System.out.println("Server main thread.");
				try {
					Thread.sleep(1000 * 60 * 60 * 24 * 365 * 100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		new Server().startServer();
	}
}


package com.my.study.io.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

public class Client {
	private AsynchronousSocketChannel client;

	private void start() {
		try {
			client = AsynchronousSocketChannel.open();
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}

		client.connect(new InetSocketAddress("127.0.0.1", 8888), null,
				new CompletionHandler<Void, Object>() {
					public void completed(Void result, Object attachment) {
						client.write(ByteBuffer
								.wrap("Request message from client.".getBytes()));
					}

					public void failed(Throwable exc, Object attachment) {
						System.out.println("Connect Failed: " + exc);
					}
				});

		final ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
		client.read(buffer, null, new CompletionHandler<Integer, Object>() {
			public void completed(Integer result, Object attachment) {
				String str = new String(buffer.array());
				System.out.println("Response from server: " + str);
			}

			public void failed(Throwable exc, Object attachment) {
				System.out.println("Read Failed: " + exc);
			}
		});
		
		while (true) {
			System.out.println("Client main thread.");
			try {
				Thread.sleep(1000 * 60 * 60 * 24 * 365 * 100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		new Client().start();
	}
}

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值