java NIO,
java NIO,
nio是new io的简称,从jdk1.4就被引入了。现在的jdk已经到了1.6了,可以说不是什么新东西了。但其中的一些思想值得我来研究。这两天,我研究了下其中的套接字部分,有一些心得,在此分享。 首先先分析下:为什么要nio套接字? nio的主要作用就是用来解决速度差异的。举个例子:计算机处理的速度,和用户按键盘的速度。这两者的速度相差悬殊。如果按照经典的方法:一个用户设定一个线程,专门等待用户的输入,无形中就造成了严重的资源浪费:每一个线程都需要珍贵的cpu时间片,由于速度差异造成了在这个交互线程中的cpu都用来等待。 nio套接字是怎么做到的? 其实,其中的思想很简单:轮询。一个线程轮询多个input;传统的方式是:有n个客户端就要有n个服务线程+一个监听线程,现在采取这种凡是,可以仅仅使用1个线程来代替n个服务线程以此来解决。 具体应用例子: 在ftp的控制连接中,因为只有少量的字符命令进行传输,所以可以考虑利用这种轮询的方式实现,以节省资源。 具体见例子。 Java代码
package com.cxz.io;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Collections;
public class IoEchoServer implements Runnable {
// ThreadLocal<Socket> localSocket = new ThreadLocal<Socket>();
Map<String, Socket> socketMap = Collections
.synchronizedMap(new HashMap<String, Socket>());
int threadCounter = 0;
synchronized private int getCounter() {
return threadCounter++;
}
public IoEchoServer() throws IOException {
ServerSocket server = new ServerSocket(1984);
while (true) {
Socket socket = server.accept();
// happened in the main thread.
// localSocket.set(socket);
String threadName = "---Thread" + getCounter() + "---";
socketMap.put(threadName, socket);
this.start(threadName);
}
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
new IoEchoServer();
}
public void run() {
try {
Socket socket = socketMap.get(Thread.currentThread().getName());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//PrintWriter out = new PrintWriter(socket.getOutputStream());
String buffer = null;
while(!"END".equals(buffer)){
buffer = in.readLine();
System.out.println(buffer);
}
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(String threadName) {
new Thread(this, threadName).start();
}
}
package com.cxz.io;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Collections;
public class IoEchoServer implements Runnable {
// ThreadLocal<Socket> localSocket = new ThreadLocal<Socket>();
Map<String, Socket> socketMap = Collections
.synchronizedMap(new HashMap<String, Socket>());
int threadCounter = 0;
synchronized private int getCounter() {
return threadCounter++;
}
public IoEchoServer() throws IOException {
ServerSocket <A title=server href="http://www.google.cn/search?sbi=server&q=server&sbb=搜索&sa=搜索&client=pub-6430022987645146&forid=1&prog=aff&ie=GB2312&oe=GB2312&hl=zh-CN" target=_blank>server</A> = new ServerSocket(1984);
while (true) {
Socket socket = <A title=server href="http://www.google.cn/search?sbi=server&q=server&sbb=搜索&sa=搜索&client=pub-6430022987645146&forid=1&prog=aff&ie=GB2312&oe=GB2312&hl=zh-CN" target=_blank>server</A>.accept();
// happened in the main thread.
// localSocket.set(socket);
String threadName = "---Thread" + getCounter() + "---";
socketMap.put(threadName, socket);
this.start(threadName);
}
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
new IoEchoServer();
}
public void run() {
try {
Socket socket = socketMap.get(Thread.currentThread().getName());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//PrintWriter out = new PrintWriter(socket.getOutputStream());
String buffer = null;
while(!"END".equals(buffer)){
buffer = in.readLine();
<A title=system href="http://www.alimama.com/membersvc/buyadzone/buy_ad_zone.htm?adzoneid=892989 " target=_blank>system</A>.out.println(buffer);
}
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(String threadName) {
new Thread(this, threadName).start();
}
}
package com.cxz.io;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Collections;
public class IoEchoServer implements Runnable {
// ThreadLocal<Socket> localSocket = new ThreadLocal<Socket>();
Map<String, Socket> socketMap = Collections
.synchronizedMap(new HashMap<String, Socket>());
int threadCounter = 0;
synchronized private int getCounter() {
return threadCounter++;
}
public IoEchoServer() throws IOException {
ServerSocket server = new ServerSocket(1984);
while (true) {
Socket socket = server.accept();
// happened in the main thread.
// localSocket.set(socket);
String threadName = "---Thread" + getCounter() + "---";
socketMap.put(threadName, socket);
this.start(threadName);
}
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
new IoEchoServer();
}
public void run() {
try {
Socket socket = socketMap.get(Thread.currentThread().getName());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//PrintWriter out = new PrintWriter(socket.getOutputStream());
String buffer = null;
while(!"END".equals(buffer)){
buffer = in.readLine();
system.out.println(buffer);
}
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(String threadName) {
new Thread(this, threadName).start();
}
} 下面这个例子采取了nio方式实现,虽然还是有阻塞部分,但是与上一个相比,效率已经大幅提高。仅仅阻塞到一个监听线程中。 Java代码
package com.cxz.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
import java.util.Set;
public class NioEchoServer {
private static Selector roller = null;
private static final int port = 8080;
private static NioEchoServer instance = null;
private ThreadLocal<StringBuffer> stringLocal = new ThreadLocal<StringBuffer>();
private NioEchoServer() throws IOException {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.socket().bind(new InetSocketAddress(port));
serverChannel.configureBlocking(false);
serverChannel.register(roller, SelectionKey.OP_ACCEPT);
}
public synchronized static NioEchoServer getInstance() throws IOException {
if (instance == null) {
roller = Selector.open();
instance = new NioEchoServer();
}
return instance;
}
public void start() throws IOException {
int keyAdded = 0;
while ((keyAdded = roller.select()) > 0) {
Set<SelectionKey> keySets = roller.selectedKeys();
Iterator iter = keySets.iterator();
while (iter.hasNext()) {
SelectionKey key = (SelectionKey) iter.next();
iter.remove();
actionHandler(key);
}
}
}
public void actionHandler(SelectionKey key) throws IOException {
if (key.isAcceptable()) {
ServerSocketChannel serverChannel = (ServerSocketChannel) key
.channel();
SocketChannel socketChannel = serverChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(roller, SelectionKey.OP_READ);
} else if (key.isReadable()) {
ByteBuffer buffer = ByteBuffer.allocate(16);
SocketChannel socketChannel = (SocketChannel) key.channel();
socketChannel.read(buffer);
buffer.flip();
String temp = decode(buffer);
StringBuffer strBuffer = stringLocal.get();
if (strBuffer == null) {
strBuffer = new StringBuffer();
}
strBuffer.append(temp);
if (temp.equals("/r/n")) {
System.out.println(strBuffer.toString());
strBuffer = null;
}
stringLocal.set(strBuffer);
}
}
public String decode(ByteBuffer buffer) {
Charset charset = null;
CharsetDecoder decoder = null;
CharBuffer charBuffer = null;
try {
charset = Charset.forName("UTF-8");
decoder = charset.newDecoder();
charBuffer = decoder.decode(buffer);
return charBuffer.toString();
} catch (Exception ex) {
ex.printStackTrace();
return "";
}
}
public static void main(String[] args) {
try {
NioEchoServer.getInstance().start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
相关文章
- 暂无相关文章
用户点评