欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java aio 网络编程 服务端  

程序员文章站 2022-03-20 18:28:14
...

    今天测试了一下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方法都已经执行结束了