Java NIO总结.docx_第1页
Java NIO总结.docx_第2页
Java NIO总结.docx_第3页
Java NIO总结.docx_第4页
Java NIO总结.docx_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

NIO:与外围设备数据通信需要channel通道,如像外部输出数据,先将数据写入缓冲区通过通道输出。如果从外部读取数据,需要通过通道channel读取到缓冲区,然后从缓冲区数据获取处理。缓冲区内部细节1 初始化 2 第一次读取3个字节到缓冲区 3 第二次读取2个字节到缓冲区 4 调用Flip,将limit设置position,position设置为0 5 调用clear,将limit设置为capacity,position设置为0NIO核心观念:通道和缓冲区(channel和Buffer)1) 块操作2) 非阻塞IO复用机制采用select模型,注册感兴趣IO事件给操作系统后,一旦这些事件发生,内核会改变这些事件的状态,通过检查这些事件的状态,便可以查找到注册过的、准备就绪的I/O 事件,然后可以流畅地进行I/O操作。传统IO阻塞调用:流 I/O 是阻塞调用的。不论是read 方法还是write 方法都能阻塞(block)一个线程直到字节被真正地读取或者写入。这意味着如果流不能立即被读取或者写入字节(通常是因为网络连接繁忙),Java 就会挂起这个调用的线程,处于等待的状态。常用Socket 的读写操作都是阻塞式的,就是说每次read/write 掉用,在数据被读入/写出前,调用线程都处于阻塞的状态.多线程耗费资源,特别是多线程间切换很耗费资源。NIO特征:l)面向块的I/O 操作2)非阻塞的I/O 操作3)字符集编码解码4)内存映射文件5)文件锁定,Reactor 模型:Reactor 模型采用分而治之的思想,将一个客户端连接的事件分成两类:I/O 事件和非I/O 事件。前者需要等待I/O 准备就绪,后者可以立即执行,因此分别进行处理。I/O 事件包括:Read(读取请求信息)、Send(发送响应信息)。非I/O 事件包括encode、compute、decode。异步连接池:首先,用户处理线程调用连接池对象的某个方法(比如sendRequest),把一个能够标识本次请求的Request 对象扔给连接池。之后用户处理线程可以去做别的事情,比如,向其他连接池发送请求。最后当用户线程处理完能做的业务逻辑后,就可以等待连接池返回结果了。(一) 读写IO:(按块缓冲区)package java.nio.io;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;import java.util.Date;/* * Project: NIO * Title: CopyFile.java * Package * Description: JAVA NIO 读取写入文件方面优势 * author * date May 16, 2013 9:51:13 AM * version V1.0 */传统IO一直是性能瓶颈,因为每次按字节读取,耗费磁头寻址次数,磁头寻址时间是固定的,次数多耗费时间就长public class CopyFile public static void main(String args) throws Exception String infile = C:copy.sql; String outfile = C:copy.txt; / 获取源文件和目标文件的输入输出流 FileInputStream fin = new FileInputStream(infile); FileOutputStream fout = new FileOutputStream(outfile); / 获取输入输出通道 FileChannel fcin = fin.getChannel();/FileChannel对象是线程安全的 FileChannel fcout = fout.getChannel(); / 每个FileChannel都有一个叫file position的概念,该position值决定文件中哪一处的数据接下来被读或写。 / FileChannel position是从底层文件描述符获取的, 当字节被read( ) 或write( ) 方法传输时,文件position会自动更新。 / MappedByteBuffer类使得我们可以通过ByteBuffer API来访问数据文件 byteBuffer(fcin,fcout); /2 秒 mapByteBuffer(fcin,fcout);/1秒 / 创建缓冲区 public static void byteBuffer(FileChannel fcin,FileChannel fcout) throws IOException ByteBuffer buffer = ByteBuffer.allocate(1024); / MappedByteBuffer mapBuffer = fcin.map(FileChannel.MapMode.READ_ONLY, 0,fcin.size(); Date start = new Date(); while (true) / clear方法重设缓冲区,使它可以接受读入的数据 buffer.clear(); / 从输入通道中将数据读到缓冲区 int r = fcin.read(buffer); / read方法返回读取的字节数,可能为零,如果该通道已到达流的末尾,则返回-1 if (r = -1) break; / flip方法让缓冲区可以将新读入的数据写入另一个通道 buffer.flip(); / 将缓冲区内容写入输出通道 fcout.write(buffer); Date end = new Date(); System.out.println(150M byteBuffer spend:+(end.getTime()-start.getTime()/1000+ sec);/150M 4秒/ 创建映射缓冲区 ,把文件的内容被映像到计算机虚拟内存的一块区域,/ 这样就可以直接操作内存当中的数据而无需操作的时候每次都通过I/O去物理硬盘读取文件public static void mapByteBuffer(FileChannel fcin,FileChannel fcout) throws IOException MappedByteBuffer mapBuffer = fcin.map(FileChannel.MapMode.READ_ONLY, 0,fcin.size();Date start = new Date();fcout.write(mapBuffer);/将映射缓冲区直接写入输出通道Date end = new Date();System.out.println(150M mapByteBuffer spend:+(end.getTime()-start.getTime()/1000+ sec);/150M 4秒(二) 异步IO:l 传统IO:服务端:public class SynchServerSocket private int port=8821; private ServerSocket serverSocket; private ExecutorService executorService;/线程池 private final int POOL_SIZE=10;/单个CPU线程池大小 public SynchServerSocket() throws IOException serverSocket = new ServerSocket(port); /Runtime的availableProcessor()方法返回当前系统的CPU数目. executorService=Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE); System.out.println(服务器启动); public void service() while(true) Socket socket=null; try /接收客户连接,只要客户进行了连接,就会触发accept();从而建立连接, /如果客户端未连接,服务端一直阻塞I/O等待连接,多线程从而耗费CPU及栈资源 socket=serverSocket.accept(); executorService.execute(new Handler(socket); catch(Exception e) e.printStackTrace(); public static void main(String args) throws IOException new SynchServerSocket().service();/服务启动一直等待连接 class Handler implements Runnable private Socket socket; public Handler(Socket socket) this.socket=socket; private PrintWriter getWriter(Socket socket) throws IOException /根据socket 获取输出流 OutputStream socketOut=socket.getOutputStream(); return new PrintWriter(socketOut,true); private BufferedReader getReader(Socket socket) throws IOException/根据socket 获取输入流 InputStream socketIn=socket.getInputStream(); return new BufferedReader(new InputStreamReader(socketIn); public String echo(String msg) return echo:+msg; public void run() try System.out.println(New connection accepted +socket.getInetAddress()+:+socket.getPort(); BufferedReader br=getReader(socket); PrintWriter pw=getWriter(socket); String msg=null; while(msg=br.readLine()!=null) System.out.println(msg); pw.println(echo(msg); if(msg.equals(bye) break; catch (IOException e) e.printStackTrace(); finally try if(socket!=null) socket.close(); catch (IOException e) e.printStackTrace(); 客户端:public class SynchClientSocket public static void main(String args) int numTasks = 10; ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i 0,才会有selectedKeys continue; /当有读或写等任何注册的事件发生 时,可以从Selector 中获得相应的SelectionKey,同时从SelectionKey /中可以找到发生的事件和该事件所发生的具体的SocketChannle继承自SelectableChannel,以获得客户端发送过来的数据。 Iterator it = selector.selectedKeys().iterator(); while (it.hasNext() SelectionKey key = (SelectionKey)it.next(); if (key.isAcceptable() /侦听端信号触发 ServerSocketChannel server = (ServerSocketChannel) key.channel(); /接受一个新的连接 SocketChannel sc = server.accept(); sc.configureBlocking(false); /设置该socket的异步信号OP_READ:当socket可读时, /触发函数DealwithData(); sc.register(selector,SelectionKey.OP_READ); else if (key.isReadable() /某socket可读信号 DealwithData(key); it.remove(); / 删除处理过的选择键 it.remove(); catch(Exception e) public void DealwithData(SelectionKey key) throws IOException int count; /由key获取指定socketchannel的引用 SocketChannel sc = (SocketChannel)key.channel(); r_buff.clear(); /读取数据到r_buff while(count = sc.read(r_buff) 0); /确保r_buff可读 r_buff.flip(); /清空写缓存 w_buff.clear(); /将r_buff内容拷入w_buff w_buff.put(r_buff); w_buff.flip();/从写缓冲区向输出通道写之前调用flip EchoToClient(sc); w_buff.clear(); r_buff.clear(); public void EchoToClient(SocketChannel sc) throws IOException while(w_buff.hasRemaining() sc.write(w_buff); public static void main(String args) if(args.length 0) port = Integer.parseInt(args0); new AsynServer(); 客户端:public class AsynClient private SocketChannel sc; private final int MAX_LENGTH = 1024; private ByteBuffer r_buff = ByteBuffer.allocate(MAX_LENGTH); private ByteBuffer w_buff = ByteBuffer.allocate(MAX_LENGTH); private static String host ; private static int port = 8848; public AsynClient() try InetSocketAddress addr = new InetSocketAddress(host,port); /生成一个socketchannel sc = SocketChannel.open(); /连接到server sc.connect(addr); while(!sc.finishConnect() ; System.out.println(connection has been established!.); while(true) /回射消息 String echo; try System.err.println(Enter msg youd like to send: ); BufferedReader br = new BufferedReader(new InputStreamReader(System.i

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论