一、NIO非阻塞式网络通信

  1.阻塞与非阻塞的概念

  1. 传统的 IO 流都是阻塞式的。也就是说,当一个线程调用 read() write()
  2. 时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不
  3. 能执行其他任务。因此,在完成网络通信进行 IO 操作时,由于线程会
  4. 阻塞,所以服务器端必须为每个客户端都提供一个独立的线程进行处理,
  5. 当服务器端需要处理大量客户端时,性能急剧下降。
  6. Java NIO 是非阻塞模式的。当线程从某通道进行读写数据时,若没有数
  7. 据可用时,该线程可以进行其他任务。线程通常将非阻塞 IO 的空闲时
  8. 间用于在其他通道上执行 IO 操作,所以单独的线程可以管理多个输入
  9. 和输出通道。因此,NIO 可以让服务器端使用一个或有限几个线程来同
  10. 时处理连接到服务器端的所有客户端。

  2.选择器

  大致的图解如下:

  

  // 通道注册到选择器上之后,选择器将会对通道进行监控,直到通道传输完全准备就绪了,才分配给服务端一个或多个线程进行处理

  3.使用NIO完成非阻塞式网络通信

  非阻塞核心有三个:(只能用于网络通信)

    通道(channel)  缓冲区(buffer)  选择器(selector)

  NIO完成的网络通信:

  1. // 客户端
  2. @Test
  3. public void client() {
  4. SocketChannel sChannel = null;
  5. FileChannel inChannel = null;
  6. try {
  7. // 获取通道(采用1.7之后的open方式)
  8. sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
  9. // 分配缓冲区
  10. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  11. // 读取本地文件(使用FileChannel),发送到服务端
  12. inChannel = FileChannel.open(Paths.get("D:\\test\\1.jpg"), StandardOpenOption.READ);
  13. while ((inChannel.read(byteBuffer)) != -1) {
  14. // 通过socketChannel写入数据
  15. byteBuffer.flip();// 切换读模式
  16. sChannel.write(byteBuffer);
  17. byteBuffer.clear();// 清空缓冲区
  18. }
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. } finally {
  22. // 务必进行通道的关闭
  23. if (inChannel != null) {
  24. try {
  25. inChannel.close();
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. if (sChannel != null) {
  31. try {
  32. sChannel.close();
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. }
  38.  
  39. }
  40. // 服务端
  41. @Test
  42. public void server() {
  43. ServerSocketChannel ssChannel = null;
  44. FileChannel outChannel = null;
  45. SocketChannel sChannel = null;
  46. try {
  47. // 开启通道
  48. ssChannel = ServerSocketChannel.open();
  49. // 绑定端口
  50. ssChannel.bind(new InetSocketAddress(9898));
  51. // 获取客户端连接的通道
  52. sChannel = ssChannel.accept();
  53. outChannel = FileChannel.open(Paths.get("D:\\test\\2.jpg"), StandardOpenOption.CREATE, StandardOpenOption.WRITE) ;
  54. // 接收客户端数据,保存到本地
  55. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  56. while ((sChannel.read(byteBuffer)) != -1){
  57. // 通道读写操作
  58. byteBuffer.flip();
  59. outChannel.write(byteBuffer);
  60. byteBuffer.clear();
  61. }
  62. } catch (IOException e) {
  63. e.printStackTrace();
  64. } finally {
  65. if (outChannel != null) {
  66. try {
  67. outChannel.close();
  68. } catch (IOException e) {
  69. e.printStackTrace();
  70. }
  71. }
  72. if (sChannel != null) {
  73. try {
  74. sChannel.close();
  75. } catch (IOException e) {
  76. e.printStackTrace();
  77. }
  78. }
  79. if (ssChannel != null) {
  80. try {
  81. ssChannel.close();
  82. } catch (IOException e) {
  83. e.printStackTrace();
  84. }
  85. }
  86. }
  87. }

  阻塞式NIO网络通信:

  1. @Test
  2. public void client() {
  3. SocketChannel sChannel = null;
  4. FileChannel inChannel = null;
  5. try {
  6. // 方式与阻塞式基本类似
  7. sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
  8. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  9. inChannel = FileChannel.open(Paths.get("D:\\test\\2.jpg"), StandardOpenOption.READ);
  10. while ((inChannel.read(byteBuffer)) != -1) {
  11. byteBuffer.flip();
  12. sChannel.write(byteBuffer);
  13. byteBuffer.clear();
  14. }
  15. // 接收服务端的反馈
  16. int len;
  17. while ((len = sChannel.read(byteBuffer)) != -1) {
  18. byteBuffer.flip();
  19. System.out.println(new String(byteBuffer.array(), 0, len));
  20. byteBuffer.clear();
  21. }
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. } finally {
  25. // 流的关闭
  26. if (inChannel != null) {
  27. try {
  28. inChannel.close();
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. if (sChannel != null) {
  34. try {
  35. sChannel.close();
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. }
  41. }
  42. @Test
  43. public void server() {
  44. ServerSocketChannel ssChannel = null;
  45. SocketChannel sChannel = null;
  46. FileChannel outChannel = null;
  47. try {
  48. ssChannel = ServerSocketChannel.open();
  49. // 绑定客户端连接
  50. ssChannel.bind(new InetSocketAddress(9898));
  51. // 获取连接
  52. sChannel = ssChannel.accept();
  53. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  54. outChannel = FileChannel.open(Paths.get("D:\\test\\3.jpg"), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
  55. while ((sChannel.read(byteBuffer)) != -1) {
  56. // 保存到本地
  57. byteBuffer.flip();
  58. outChannel.write(byteBuffer);
  59. byteBuffer.clear();
  60. }
  61. // 发送反馈
  62. String str = "服务端接收成功!";
  63. byteBuffer.put(str.getBytes());
  64. byteBuffer.flip();
  65. sChannel.write(byteBuffer);
  66. } catch (IOException e) {
  67. e.printStackTrace();
  68. } finally {
  69. if (outChannel != null) {
  70. try {
  71. outChannel.close();
  72. } catch (IOException e) {
  73. e.printStackTrace();
  74. }
  75. }
  76. if (sChannel != null) {
  77. try {
  78. sChannel.close();
  79. } catch (IOException e) {
  80. e.printStackTrace();
  81. }
  82. }
  83. if (ssChannel != null) {
  84. try {
  85. ssChannel.close();
  86. } catch (IOException e) {
  87. e.printStackTrace();
  88. }
  89. }
  90. }
  91. }

  结果:无法接收有效结束的反馈,不知道客户端是否发送完成

  

  目前可以通过显式的将客户端接收反馈之前发送状态设置为shutdowm:

  1. sChannel.shutdownOutput();
  1. @Test
  2. public void client() {
  3. SocketChannel sChannel = null;
  4. FileChannel inChannel = null;
  5. try {
  6. // 方式与阻塞式基本类似
  7. sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
  8. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  9. inChannel = FileChannel.open(Paths.get("D:\\test\\2.jpg"), StandardOpenOption.READ);
  10. while ((inChannel.read(byteBuffer)) != -1) {
  11. byteBuffer.flip();
  12. sChannel.write(byteBuffer);
  13. byteBuffer.clear();
  14. }
  15. sChannel.shutdownOutput();
  16. // 接收服务端的反馈
  17. int len;
  18. while ((len = sChannel.read(byteBuffer)) != -1) {
  19. byteBuffer.flip();
  20. System.out.println(new String(byteBuffer.array(), 0, len));
  21. byteBuffer.clear();
  22. }
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. } finally {
  26. // 流的关闭
  27. if (inChannel != null) {
  28. try {
  29. inChannel.close();
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. if (sChannel != null) {
  35. try {
  36. sChannel.close();
  37. } catch (IOException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. }
  42. }
  43. @Test
  44. public void server() {
  45. ServerSocketChannel ssChannel = null;
  46. SocketChannel sChannel = null;
  47. FileChannel outChannel = null;
  48. try {
  49. ssChannel = ServerSocketChannel.open();
  50. // 绑定客户端连接
  51. ssChannel.bind(new InetSocketAddress(9898));
  52. // 获取连接
  53. sChannel = ssChannel.accept();
  54. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  55. outChannel = FileChannel.open(Paths.get("D:\\test\\3.jpg"), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
  56. while ((sChannel.read(byteBuffer)) != -1) {
  57. // 保存到本地
  58. byteBuffer.flip();
  59. outChannel.write(byteBuffer);
  60. byteBuffer.clear();
  61. }
  62. // 发送反馈
  63. String str = "服务端接收成功!";
  64. byteBuffer.put(str.getBytes());
  65. byteBuffer.flip();
  66. sChannel.write(byteBuffer);
  67. } catch (IOException e) {
  68. e.printStackTrace();
  69. } finally {
  70. if (outChannel != null) {
  71. try {
  72. outChannel.close();
  73. } catch (IOException e) {
  74. e.printStackTrace();
  75. }
  76. }
  77. if (sChannel != null) {
  78. try {
  79. sChannel.close();
  80. } catch (IOException e) {
  81. e.printStackTrace();
  82. }
  83. }
  84. if (ssChannel != null) {
  85. try {
  86. ssChannel.close();
  87. } catch (IOException e) {
  88. e.printStackTrace();
  89. }
  90. }
  91. }
  92. }

  非阻塞式网络通信

  1. // 客户端
  2. @Test
  3. public void client() {
  4. SocketChannel sChannel = null;
  5. try {
  6. // 开启通道
  7. sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
  8. // 切换成非阻塞模式
  9. sChannel.configureBlocking(false);
  10. // 分配缓冲区
  11. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  12. // 发送数据给服务端(发送时间),数据是存放在缓冲区中
  13. byteBuffer.put(LocalDateTime.now().toString().getBytes());
  14. // 将缓冲区传送给服务端
  15. byteBuffer.flip();
  16. sChannel.write(byteBuffer);
  17. byteBuffer.clear();
  18. } catch (IOException e) {
  19. e.printStackTrace();
  20. } finally {
  21. if (sChannel != null) {
  22. try {
  23. sChannel.close();
  24. } catch (IOException e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. }
  29. }
  30. // 服务端
  31. @Test
  32. public void server() {
  33. ServerSocketChannel ssChannel = null;
  34. SocketChannel sChannel = null;
  35. try {
  36. // 开启通道
  37. ssChannel = ServerSocketChannel.open();
  38. // 切换非阻塞模式
  39. ssChannel.configureBlocking(false);
  40. // 绑定连接
  41. ssChannel.bind(new InetSocketAddress(9898));
  42. // 获取选择器,同样的open方法
  43. Selector selector = Selector.open();
  44. // 将通道注册到选择器上,后一个参数表示选择键,也就是监控通道的什么状态
  45. ssChannel.register(selector, SelectionKey.OP_ACCEPT);// 监听接收
  46. // 通过选择器轮巡式选择已经“准备就绪“的事件
  47. while (selector.select() > 0) {
  48. // 获取当前选择器中所有注册的选择键
  49. Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
  50. // 迭代器迭代
  51. while (iterator.hasNext()) {
  52. // 获取准备就绪的事件
  53. SelectionKey selectionKey = iterator.next();
  54. // 判断就绪的事件
  55. if (selectionKey.isAcceptable()) {
  56. // 若接收就绪,则获取客户端连接
  57. sChannel = ssChannel.accept();
  58. // 切换为非阻塞模式
  59. sChannel.configureBlocking(false);
  60. // 将该通道注册到选择器上,监控读就绪状态
  61. sChannel.register(selector, SelectionKey.OP_READ);
  62. } else if (selectionKey.isReadable()) {
  63. // 获取选择器上读就绪状态的通道(需要强转)
  64. sChannel = (SocketChannel) selectionKey.channel();
  65. // 读取数据
  66. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  67. int len;
  68. while ((len = sChannel.read(byteBuffer)) > 0) {
  69. byteBuffer.flip();
  70. System.out.println(new String(byteBuffer.array(), 0, len));
  71. byteBuffer.clear();
  72. }
  73. }
  74. // 取消选择键(防止出现传输完成了应该重置而还显示完成的情况)
  75. iterator.remove();
  76. }
  77. }
  78. } catch (IOException e) {
  79. e.printStackTrace();
  80. }
  81. }

  结果:可以轮巡接收客户端返回的时间

  

  // UDP的DataGramChannel类似,暂不展开

  1. package com.atguigu.nio;
  2.  
  3. import java.io.IOException;
  4. import java.net.InetSocketAddress;
  5. import java.nio.ByteBuffer;
  6. import java.nio.channels.DatagramChannel;
  7. import java.nio.channels.SelectionKey;
  8. import java.nio.channels.Selector;
  9. import java.util.Date;
  10. import java.util.Iterator;
  11. import java.util.Scanner;
  12.  
  13. import org.junit.Test;
  14.  
  15. public class TestNonBlockingNIO2 {
  16.  
  17. @Test
  18. public void send() throws IOException{
  19. DatagramChannel dc = DatagramChannel.open();
  20.  
  21. dc.configureBlocking(false);
  22.  
  23. ByteBuffer buf = ByteBuffer.allocate(1024);
  24.  
  25. Scanner scan = new Scanner(System.in);
  26.  
  27. while(scan.hasNext()){
  28. String str = scan.next();
  29. buf.put((new Date().toString() + ":\n" + str).getBytes());
  30. buf.flip();
  31. dc.send(buf, new InetSocketAddress("127.0.0.1", 9898));
  32. buf.clear();
  33. }
  34.  
  35. dc.close();
  36. }
  37.  
  38. @Test
  39. public void receive() throws IOException{
  40. DatagramChannel dc = DatagramChannel.open();
  41.  
  42. dc.configureBlocking(false);
  43.  
  44. dc.bind(new InetSocketAddress(9898));
  45.  
  46. Selector selector = Selector.open();
  47.  
  48. dc.register(selector, SelectionKey.OP_READ);
  49.  
  50. while(selector.select() > 0){
  51. Iterator<SelectionKey> it = selector.selectedKeys().iterator();
  52.  
  53. while(it.hasNext()){
  54. SelectionKey sk = it.next();
  55.  
  56. if(sk.isReadable()){
  57. ByteBuffer buf = ByteBuffer.allocate(1024);
  58.  
  59. dc.receive(buf);
  60. buf.flip();
  61. System.out.println(new String(buf.array(), 0, buf.limit()));
  62. buf.clear();
  63. }
  64. }
  65.  
  66. it.remove();
  67. }
  68. }
  69.  
  70. }

  注册选择器时的选择键:多个请使用或 | 连接

  1. : SelectionKey.OP_READ 1
  2. : SelectionKey.OP_WRITE 4
  3. 连接 : SelectionKey.OP_CONNECT 8
  4. 接收 : SelectionKey.OP_ACCEPT 16

  4.管道

  

  示例:

  1. @Test
  2. public void test1() {
  3. Pipe pipe = null;
  4. Pipe.SinkChannel sinkChannel = null;
  5. Pipe.SourceChannel sourceChannel = null;
  6. try {
  7. // 获取管道,经典的open方法获取
  8. pipe = Pipe.open();
  9. // 将缓冲区数据写入管道
  10. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  11. byteBuffer.put("通过单向管道发送数据".getBytes());
  12. sinkChannel = pipe.sink();
  13. byteBuffer.flip();
  14. sinkChannel.write(byteBuffer);
  15.  
  16. // 读取缓冲区中的数据
  17. sourceChannel = pipe.source();
  18. int len;
  19. byteBuffer.flip();
  20. len = sourceChannel.read(byteBuffer);
  21. System.out.println(new String(byteBuffer.array(), 0, len));
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. } finally {
  25. if (sinkChannel != null) {
  26. try {
  27. sinkChannel.close();
  28. } catch (IOException e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. if (sourceChannel != null) {
  33. try {
  34. sourceChannel.close();
  35. } catch (IOException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. }
  40.  
  41. }

  //实际使用时可以两个线程公用一个pipe进行数据的传输

二、NIO2——Path Paths Files

  JDK7新增Path接口,Paths工具类,Files工具类。 这些接口和工具类对NIO中的功能进行了高度封装,大大简化了文件系统的IO编程。

  在传统java.io中, 文件和目录都被抽象成File对象, 即 File file = new File(".");

  NIO.2中则引入接口Path代表与平台无关的路径,文件和目录都用Path对象表示。比起传统File类,它更高效,更方便。

  作为与平台无关的系统访问支持;它的出现,就是为了替代 java.io.File

  Paths工具类——提供获取Path的两个静态方法:

   

  1. @Test
  2. public void test1() {
  3. Path path1 = Paths.get("D:\\test\\nio");
  4. Path path2 = Paths.get("D:\\test", "nio2", "hello.txt");
  5. System.out.println(path1);
  6. System.out.println(path2);
  7. }

  

  //实现了 toString方法,直接输出即可看到根据当前平台产生的路径

  Path接口

    getNameCount()——返回路径中的节点数量

  1. @Test
  2. public void test1() {
  3. Path path1 = Paths.get("D:\\test\\nio");
  4. Path path2 = Paths.get("D:\\test", "nio2", "hello.txt");
  5. System.out.println(path1);
  6. System.out.println(path2);
  7. System.out.println(path1.getNameCount());
  8. System.out.println(path2.getNameCount());
  9. }

  

    getRoot()——返回根节点,win中是盘符 C D,Linux中是 /,返回的新的Path只包含根节点

  1. @Test
  2. public void test1() {
  3. Path path1 = Paths.get("D:\\test\\nio");
  4. Path path2 = Paths.get("D:\\test", "nio2", "hello.txt");
  5. System.out.println(path1);
  6. System.out.println(path2);
  7. System.out.println(path1.getRoot());
  8. System.out.println(path2.getRoot());
  9. }

  

    toAbsolutePath()——返回绝对路径,若Path初始化时为绝对路径,则返回原路径;若是相对路径,则返回与上级路径合成的绝对路径

  1. @Test
  2. public void test1() {
  3. Path path1 = Paths.get("person.txt");
  4. Path path2 = Paths.get("D:\\test", "nio2", "hello.txt");
  5. System.out.println(path1);
  6. System.out.println(path2);
  7. System.out.println(path1.toAbsolutePath());
  8. System.out.println(path2.toAbsolutePath());
  9. }

    

  更多常见方法:

  1. boolean endsWith(String path) : 判断是否以 path 路径结束
  2. boolean startsWith(String path) : 判断是否以 path 路径开始
  3. boolean isAbsolute() : 判断是否是绝对路径
  4. Path getFileName() : 返回与调用 Path 对象关联的文件名
  5. Path getName(int idx) : 返回的指定索引位置 idx 的路径名称
  6. int getNameCount() : 返回Path 根目录后面元素的数量
  7. Path getParent() :返回Path对象包含整个路径,不包含 Path 对象指定的文件路径
  8. Path getRoot() :返回调用 Path 对象的根路径
  9. Path resolve(Path p) :将相对路径解析为绝对路径
  10. Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象
  11. String toString() 返回调用 Path 对象的字符串表示形式

  深入讲解参见:http://blog.csdn.net/lirx_tech/article/details/51416672

  Files工具类——完善的OS文件系统支持

    copy——复制文件

  1. @Test
  2. public void test1() {
  3. Path src = Paths.get("D:\\test\\1.jpg");
  4. Path dst = Paths.get("D:\\test", "2.jpg");
  5. try {
  6. Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING);
  7. } catch (IOException e) {
  8. e.printStackTrace();
  9. }
  10.  
  11. }
  12. }

    BufferedWriter——写入字符串

  1. @Test
  2. public void test1() {
  3. Path src = Paths.get("D:\\test\\hello.txt");
  4. BufferedWriter writer = null;
  5. try {
  6. writer = Files.newBufferedWriter(src, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
  7. writer.write("Hello Files!");
  8. } catch (IOException e) {
  9. e.printStackTrace();
  10. } finally {
  11. if (writer != null) {
  12. try {
  13. writer.close();
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. }
  19.  
  20. }

  其它诸如返回文件的大小,删除一个文件,以及与File的转换等等请参见以下随笔、常用方法列表或API:

  几个示例:http://www.cnblogs.com/digdeep/p/4478734.html

  常用方法:

  1. Path copy(Path src, Path dest, CopyOption how) : 文件的复制
  2. Path createDirectory(Path path, FileAttribute<?> attr) : 创建一个目录
  3. Path createFile(Path path, FileAttribute<?> arr) : 创建一个文件
  4. void delete(Path path) : 删除一个文件
  5. Path move(Path src, Path dest, CopyOptionhow) : src 移动到 dest 位置
  6. long size(Path path) : 返回 path 指定文件的大小
  7. Files常用方法:用于判断
  8. boolean exists(Path path, LinkOption opts) : 判断文件是否存在
  9. boolean isDirectory(Path path, LinkOption opts) : 判断是否是目录
  10. boolean isExecutable(Path path) : 判断是否是可执行文件
  11. boolean isHidden(Path path) : 判断是否是隐藏文件
  12. boolean isReadable(Path path) : 判断文件是否可读
  13. boolean isWritable(Path path) : 判断文件是否可写
  14. boolean notExists(Path path, LinkOption opts) : 判断文件是否不存在
  15. public static <A extends BasicFileAttributes> A readAttributes(Path path,Class<A> type,LinkOption...
  16. options) : 获取与 path 指定的文件相关联的属性。
  17. Files常用方法:用于操作内容
  18. SeekableByteChannel newByteChannel(Path path, OpenOptionhow) : 获取与指定文件的连接,
  19. how 指定打开方式。
  20. DirectoryStream newDirectoryStream(Path path) : 打开 path 指定的目录
  21. InputStream newInputStream(Path path, OpenOptionhow):获取 InputStream 对象
  22. OutputStream newOutputStream(Path path, OpenOptionhow) : 获取 OutputStream 对象

Java基础——NIO(二)非阻塞式网络通信与NIO2新增类库的更多相关文章

  1. JAVA NIO学习三:NIO 的非阻塞式网络通信

    紧接着上一章,我们继续来研究NIO,上一章中我们讲了NIO 中最常见的操作即文件通道的操作,但实际上NIO的主要用途还是在于网络通信,那么这个时候就会涉及到选择器,这一章我们就会对其进行讲解操作. 一 ...

  2. 4.NIO的非阻塞式网络通信

    /*阻塞 和 非阻塞 是对于 网络通信而言的*/ /*原先IO通信在进行一些读写操作 或者 等待 客户机连接 这种,是阻塞的,必须要等到有数据被处理,当前线程才被释放*/ /*NIO 通信 是将这个阻 ...

  3. NIO 的非阻塞式网络通信

    1.阻塞与非阻塞   ①  传统的 IO 流都是阻塞式的.也就是说,当一个线程调用 read() 或 write()时, 该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务. 因 ...

  4. JAVA NIO学习记录2-非阻塞式网络通信

    一.阻塞与非阻塞 传统的IO 流都是阻塞式的.也就是说,当一个线程调用read() 或write() 时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务.因此,在完成网络通信 ...

  5. Java IO(3)非阻塞式输入输出(NIO)

    在上篇<Java IO(2)阻塞式输入输出(BIO)>的末尾谈到了什么是阻塞式输入输出,通过Socket编程对其有了大致了解.现在再重新回顾梳理一下,对于只有一个“客户端”和一个“服务器端 ...

  6. JAVA基础知识之网络编程——-基于NIO的非阻塞Socket通信

    阻塞IO与非阻塞IO 通常情况下的Socket都是阻塞式的, 程序的输入输出都会让当前线程进入阻塞状态, 因此服务器需要为每一个客户端都创建一个线程. 从JAVA1.4开始引入了NIO API, NI ...

  7. Java基础知识强化之多线程笔记07:同步、异步、阻塞式、非阻塞式 的联系与区别

    1. 同步: 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.但是一旦调用返回,就必须先得到返回值了. 换句话话说,调用者主动等待这个"调用"的结果. 对于 ...

  8. NIO非阻塞式编程

    /** * NIO非阻塞式编程<p> * 服务端和客户端各自维护一个管理通道的对象,我们称之为selector,该对象能检测一个或多个通道 (channel) 上的事件. * 我们以服务端 ...

  9. Socket-IO 系列(三)基于 NIO 的同步非阻塞式编程

    Socket-IO 系列(三)基于 NIO 的同步非阻塞式编程 缓冲区(Buffer) 用于存储数据 通道(Channel) 用于传输数据 多路复用器(Selector) 用于轮询 Channel 状 ...

随机推荐

  1. ADF系列-3.VO的查询

    一·VO的计数查询 VO的计数查询有四种方式: 1.ViewObjectImpl::getRowCount() 这个方法从数据库中提取所有行,然后对每一行计数, 得到总行数.如果行数很大,这会影响性能 ...

  2. [USACO5.2]Snail Trails

    嘟嘟嘟 一道很水的爆搜题,然后我调了近40分钟…… 错误:输入数据最好用cin,因为数字可能不止一位,所以用scanf后,单纯的c[0]为字母,c[1]数字………………………… #include< ...

  3. [19/04/02-星期二] IO技术_字符流分类总结(含字符转换流InputStreamReader/ OutputStreamWriter,实现字节转字符)

    一.概念 ------->1.BufferedReader/BufferedWriter [参考19.03.31文章] *Reader/Writer-------->2.InputStre ...

  4. C#string byte[] base64位互相转换

    byte表示字节,byte[]则表示存放一系列字节的数组 1个字符=2个字节(byte) 1个字节=8个比特(bit) 网速上所说的1M其实是指1兆的小b,1M= 1024b/8 = 128kb 下面 ...

  5. 关于JWT.NET

    1.JWT的概念: JWT全称是Json Web Token,是一种用于双方之间传递安全信息的简洁的.URL安全的表述性声明规范.JWT作为一个开放的标准( RFC 7519 ),定义了一种简洁的,自 ...

  6. 二十五、详述 IntelliJ IDEA 提交代码前的 Code Analysis 机制

    在我们用 IntelliJ IDEA 向 SVN 或者 Git 提交代码的时候,IntelliJ IDEA 提供了一个自动分析代码的功能,即Perform code analysis: 如上图所示,当 ...

  7. PAT——1001. 害死人不偿命的(3n+1)猜想

    卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反复砍下去,最后一定在某一步得到n=1.卡拉兹在1950年的世界数 ...

  8. VS2008 工具栏CMFCToolBar的使用总结(转)

    (一)自定义工具栏 自定义工具栏,分两种情况:一是直接添加工具栏,并自己绘制图标:二是,添加工具栏,然后与BMP关联,与VC6.0中的自定义彩色工具栏类似. 1.  自绘工具栏 1)添加Toolbar ...

  9. CodeForces - 616C(很有意思的bfs,set,map的使用)

    传送门: http://codeforces.com/problemset/problem/616/C C. The Labyrinth time limit per test 1 second me ...

  10. 第28章 LTDC—液晶显示中英文

    本章参考资料:<STM32F76xxx参考手册>.<STM32F7xx规格书>.库帮助文档<STM32F779xx_User_Manual.chm>. 关于开发板配 ...