首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

IO的阻塞与非阻塞、同步与异步以及Java网络IO交互方式(2)

IO的阻塞与非阻塞、同步与异步以及Java网络IO交互方式(2)

讨论

  说实话,网上关于同步与异步、阻塞与非阻塞的文章多之又多,大部分是拷贝的,也有些写的非常好的。参考了许多,也借鉴了许多,也经过自己的思考。
  同步与异步、阻塞与非阻塞之间确实有很多相似的地方,很容易混淆。wiki更是把异步与非阻塞画上了等号,更多的人还是认为他们是不同的。原因可能有很多,每个人的知识背景不同,设定的上下文也不同。
  我的看法是:在IO中,根据上面同步异步的概念,也可以看出来同步与异步往往是通过阻塞非阻塞的形式来表达的,并且是通过一种中间处理机制来达到异步的效果。同步与异步往往是IO操作请求者和回应者之间在IO实际操作阶段的协作方式,而阻塞非阻塞更确切的说是一种自身状态,当前进程或者线程的状态。
  在发出IO读请求后,阻塞IO会一直等待有数据可读,当有数据可读时,会等待数据从内核拷贝至系统进程;而非阻塞IO都会立即返回至于数据怎么处理是程序进程自己的事情,无关同步和异步。 
两种方式的组合
  组合的方式当然有四种,分别是:同步阻塞、同步非阻塞、异步阻塞、异步非阻塞。
Java网络IO实现和IO模型


不同的操作系统上有不同的IO模型,《Unix网络编程卷》将unix上的IO模型分为5类:
blocking I/O、nonblocking I/O、I/O multiplexing (select and poll)、signal driven I/O (SIGIO)以及asynchronous I/O (the POSIX aio_functions)。具体可参考Unix网络编程卷1》6.2章节

在windows上IO模型也是有5种:select 、WSAAsyncSelect、WSAEventSelect、Overlapped I/O 事件通知以及IOCP。具体可参考windows五种IO模型
  Java是平台无关的语言,在不同的平台上会调用底层操作系统的不同的IO实现,下面就来说一下Java提供的网络IO的工具和实现,为了扩大阻塞非阻塞的直观感受,我都使用了长连接。

阻塞IO

同步阻塞最常用的一种用法,使用也是最简单的,但是 I/O 性能一般很差,CPU 大部分在空闲状态。下面是一个简单的基于TCP的同步阻塞的Socket服务端例子:

[url=][/url]
1     @Test 2     public void testJIoSocket() throws Exception 3     { 4         ServerSocket serverSocket = new ServerSocket(10002); 5         Socket socket = null; 6         try 7         { 8             while (true) 9             {10                 socket = serverSocket.accept();11                 System.out.println("socket连接:" + socket.getRemoteSocketAddress().toString());12                 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));13                 while(true)14                 {15                     String readLine = in.readLine();16                     System.out.println("收到消息" + readLine);17                     if("end".equals(readLine))18                     {19                         break;20                     }21                     //客户端断开连接22                     socket.sendUrgentData(0xFF);23                 }24             }25         }26         catch (SocketException se)27         {28             System.out.println("客户端断开连接");29         }30         catch (IOException e)31         {32             e.printStackTrace();33         }34         finally35         {36             System.out.println("socket关闭:" + socket.getRemoteSocketAddress().toString());37             socket.close();38         }39     }[url=][/url]

  使用SocketTest作为客户端工具进行测试,同时开启2个客户端连接Server端并发送消息,如下图:


  再看下后台的打印
socket连接:/127.0.0.1:54080收到消息hello!收到消息my name is client1
继承事业,薪火相传
返回列表