TCP/IP学习笔记四:NIO的网络编程-多线程实例
标签(空格分隔): 网络编程 NIO 多线程
NIO的多线程编程
对于单线程的程序来说,我们无法达到并行处理,我们要向达到并行处理,必定会使用多线程,但是我们哪些代码使用子线程呢?我们可以对单线程程序进行分析,在程序中最耗时的操作就是I/O操作(读和写)。找到入口就进行改造程序。
服务器端修改代码:
package com.socket.nio3;
import java.io.IOException;
import java.net.InetSocketAddress;
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;
/**
* NIO 服务器端
*
* @author MOTUI
*
*/
public class NIOServerSocket {
private static Selector selector = null;
public static void main(String[] args) throws IOException {
// 1.创建ServerSocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 2.绑定端口
serverSocketChannel.bind(new InetSocketAddress(8989));
// 3.设置为非阻塞
serverSocketChannel.configureBlocking(false);
// 4.创建通道选择器
selector = Selector.open();
/*
* 5.注册事件类型
*
* sel:通道选择器
* ops:事件类型 ==>SelectionKey:包装类,包含事件类型和通道本身。四个常量类型表示四种事件类型
* SelectionKey.OP_ACCEPT 获取报文 SelectionKey.OP_CONNECT 连接
* SelectionKey.OP_READ 读 SelectionKey.OP_WRITE 写
*/
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
System.out.println("服务器端:正在监听8989端口");
// 6.获取可用I/O通道,获得有多少可用的通道
int num = selector.select();
if (num > 0) { // 判断是否存在可用的通道
// 获得所有的keys
Set<SelectionKey> selectedKeys = selector.selectedKeys();
// 使用iterator遍历所有的keys
Iterator<SelectionKey> iterator = selectedKeys.iterator();
// 迭代遍历当前I/O通道
while (iterator.hasNext()) {
// 获得当前key
SelectionKey key = iterator.next();
// 调用iterator的remove()方法,并不是移除当前I/O通道,标识当前I/O通道已经处理。
iterator.remove();
// 判断事件类型,做对应的处理
if (key.isAcceptable()) {
ServerSocketChannel ssChannel = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = ssChannel.accept();
System.out.println("处理请求:"+ socketChannel.getRemoteAddress());
// 获取客户端的数据
// 设置非阻塞状态
socketChannel.configureBlocking(false);
// 注册到selector(通道选择器)
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
//调用读操作工具类
RequestProcessor.ProcessorRequest(key,selector);
} else if (key.isWritable()) {
//调用写操作工具类
ResponeProcessor.ProcessorRespone(key);
}
}
}
}
}
}
RequestProcessor:
package com.socket.nio3;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 读操作的工具类
* @author MOTUI
*
*/
public class RequestProcessor {
//构造线程池
private static ExecutorService executorService = Executors.newFixedThreadPool(10);
public static void ProcessorRequest(final SelectionKey key,final Selector selector){
//获得线程并执行
executorService.submi