java aio 网络编程 服务端

    今天测试了一下AsynchronousServerSocketChannel进行网络编程,发现这个效率确实高。讲一下测试场景,AsynchronousServerSocketChannel监听连接,获取到连接以后,提交给线程池去执行任务。一开始有些地方比较迷惑,比如启动一个5个线程的连接池,当我有10个连接进来,按照每一个连接都会封装成任务的做法,岂不是有五个一开始会等待,直到之前的五个中有任务执行完了,剩余的五个任务才会陆续执行,这样的话,为什么人们都说它效率高呢?

    反正我一开始是有这个想法,于是我写了个测试,验证我的想法,发现并不是我想的那样,先看看代码,然后再详细说明一下。

package com.pzn.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class AioServer {
	
	public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
		//
		ThreadPoolExecutor pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
		
		//
		AsynchronousServerSocketChannel boss = AsynchronousServerSocketChannel.open();
		boss.bind(new InetSocketAddress("127.0.0.1", 9000));
		
		while (true) {
			
			System.out.println("active thread... " + pool.getActiveCount());
			
			AsynchronousSocketChannel worker = boss.accept().get();
			System.out.println("accepted a new connect.");
			pool.submit(new Task(worker));
		}
		
	}
	
}

   

package com.pzn.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.TimeUnit;

public class Task implements Runnable {
	
	private final AsynchronousSocketChannel worker;
	
	public Task(AsynchronousSocketChannel worker) {
		this.worker = worker;
	}
	
	public void run() {
		try {
			worker.write(ByteBuffer.wrap("i am server.".getBytes("utf-8")), null, new CompletionHandler<Integer, Object>() {
				public void completed(Integer result, Object attachment) {
					try {
						TimeUnit.SECONDS.sleep(5);
						System.out.println("write completed.");
						worker.close();
					} catch (InterruptedException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				public void failed(Throwable exc, Object attachment) {
					System.out.println("write failed.");
				}
			});
			System.out.println(Thread.currentThread() + " execute Asynchronous task.");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

}

    Task这个任务中,调用AsynchronousSocketChannel的write方法使用异步的方式,最后一个参数是回调,当server写数据完成后,会执行回调中的方法,我在回调方法completed中睡眠5秒时为了观察效果,看看线程池是否可以超过5个任务同时连接。

    结果表明,是可以的。实际上这个Task的run方法会立即执行完,根本不会去管回调中的睡眠时间,这样就相当于线程池会马上有空闲线程来处理新的连接,当然还是有一点的延迟,但不至于延迟等待5秒。特别要注意的是:执行回掉的方法,这个就不是我们所能干预的了,依赖操作系统的机制来进入回调,回调方法的执行已经和线程池没有关系了,因为所有提交的Task的run方法都已经执行结束了

猜你喜欢

转载自kibear.iteye.com/blog/2321766