java的nio之:java的bio流下实现的socket服务器同步阻塞模型和socket的伪异步的socket服务器的通信模型

简介: 同步I/O模型的弊端===>每一个线程的创建都会消耗服务端内存,当大量请求进来,会耗尽内存,导致服务宕机伪异步I/O的弊端分析===>当对Socket的输入流进行读取操作的时候,它会一直阻塞下去,知道发生如下三件事情(1)有数据可读(2)可用数据已经读取完毕(3)发生空指针或者I/O异常===>这意味着当对方发送请求或应答消息比较缓慢,或者网络传输比较慢时候,读取输入流的一方的通信线程将被长时间阻塞。

同步I/O模型的弊端
===>每一个线程的创建都会消耗服务端内存,当大量请求进来,会耗尽内存,导致服务宕机

伪异步I/O的弊端分析
===>当对Socket的输入流进行读取操作的时候,它会一直阻塞下去,知道发生如下三件事情
(1)有数据可读
(2)可用数据已经读取完毕
(3)发生空指针或者I/O异常
===>这意味着当对方发送请求或应答消息比较缓慢,或者网络传输比较慢时候,读取输入流的一方的通信线程将被长时间阻塞。在阻塞期间,其他接入的消息只能在消息队列中排队。
===>伪异步I/O实际上仅仅只是对之前I/O线程模型的一个简单优化,它无法从根本上解决同步I/O导致的通信线程阻塞问题,下面我们简单分析下如果通信对方返回应答时间过长,会引起的级联鼓掌。
(1)服务端处理缓慢,返回应答消息耗费60s,平时只需要10ms
(2)采用伪异步I/O线程正在读取故障服务节点的响应,由于读取输入流是阻塞的。因此,它将会被同步阻塞60s
(3)假如所有的可用线程都被故障服务器阻塞,那后续所有的I/O消息都将在队列中排队。
(4)由于线程池采用阻塞队列实现,当队列积满之后,后续入队列的操作将被阻塞
(5)由于前端只有一个Accptor线程接收客户端接入,它被阻塞在线程池的同步阻塞队列之后,新的客户端请求消息将被拒绝,客户端会发生大量的连接超时。
(6)由于几乎所有的链接都超时,调用者会认为系统崩溃,无法接收新的请求消息。

【一】同步阻塞I/O服务端通信模型

 

第一:socket同步阻塞服务器的启动

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.IOException;
 4 import java.net.ServerSocket;
 5 import java.net.Socket;
 6 
 7 /**
 8  * 时间服务器
 9  * 基于同步阻塞I/O实现的服务器模型
10  * @author sxf
11  *
12  */
13 public class TimerServer {
14     
15     /**
16      * 启动timerServer服务器
17      */
18     public   void init(){
19         int port=8000;
20         //创建Socket服务
21         ServerSocket server=null;
22         try {
23             server=new ServerSocket(port);
24             System.out.println("TimerServer.init()===>the time server is start in port"+port);
25             Socket socket=null;
26             while(true){
27                 //获取一次socket请求
28                 socket=server.accept();
29                 //启动一个新线程处理socket请求
30                 new Thread(new TimerServerHandler(socket)).start();
31             }
32         } catch (IOException e) {
33             e.printStackTrace();
34         }finally{
35             if(server!=null){
36                 try {
37                     server.close();
38                 } catch (IOException e) {
39                     // TODO Auto-generated catch block
40                     e.printStackTrace();
41                 }
42             }
43             server=null;
44         }
45         
46     }
47 
48     
49     public static void main(String[] args) {
50         //启动timerServer服务
51         TimerServer timerServer=new TimerServer();
52         timerServer.init();
53     }
54 }
View Code

第二:soket服务器接收到请求的处理类

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.io.PrintWriter;
 7 import java.net.Socket;
 8 import java.util.Date;
 9 
10 /**
11  * 时间服务器接受socket请求的处理类
12  * @author sxf
13  * 继承Runnable接口的线程类
14  *
15  */
16 public class TimerServerHandler implements Runnable {
17     
18     private Socket socket;
19 
20     public TimerServerHandler(Socket socket) {
21         this.socket=socket;
22     }
23     
24     /**
25      * 处理socket请求的线程体
26      */
27     @Override
28     public void run() {
29         BufferedReader in=null;
30         PrintWriter out=null;
31         try {
32             //获取请求的输入流
33             in=new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
34             //获取响应请求的输出流
35             out=new PrintWriter(this.socket.getOutputStream(),true);
36             
37             String currentTime=null;
38             String body=null;
39             //读取请求输入流的内容获取请求信息
40             while(true){
41                 body=in.readLine();
42                 if(body==null){
43                     break;
44                 }
45                 //打印请求信息
46                 System.out.println("TimerServerHandler.run()==>the time server receive order:"+body);
47                 
48                 //处理请求信息
49                 if("shangxiaofei".equals(body)){
50                     currentTime=new Date(System.currentTimeMillis()).toString();
51                 }else{
52                     currentTime="you is not get time";
53                 }
54                 //响应请求信息
55                 out.println(currentTime);
56             }
57             
58         } catch (IOException e) {
59             e.printStackTrace();
60         }finally{
61             if(in!=null){
62                 try {
63                     in.close();
64                 } catch (IOException e) {
65                     // TODO Auto-generated catch block
66                     e.printStackTrace();
67                 }
68             }
69             
70             if(out!=null){
71                 out.close();
72             }
73             
74             if(this.socket!=null){
75                 try {
76                     socket.close();
77                 } catch (IOException e) {
78                     // TODO Auto-generated catch block
79                     e.printStackTrace();
80                 }
81             }
82             
83             this.socket=null;
84         }
85         
86         
87         
88         
89     }
90 
91 }
View Code

第三:向socket服务器发送请求

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.io.PrintWriter;
 7 import java.net.Socket;
 8 
 9 /**
10  * 创建一个客户端请求
11  * @author sxf
12  *
13  */
14 public class TimerClient {
15     
16     
17     
18     public static void main(String[] args) {
19         int port=8000;
20         Socket socket=null;
21         BufferedReader in=null;
22         PrintWriter out=null;
23         try {
24             socket=new Socket("127.0.0.1",port);
25             in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
26             out=new PrintWriter(socket.getOutputStream(),true);
27             //发送请求
28             out.println("shangxiaofei!=");
29             System.out.println("TimerClient.main()send order to server success");
30             
31             //等待服务器响应
32             String resp=in.readLine();
33             System.out.println("TimerClient.main(Now is:)"+resp);
34         } catch (Exception e) {
35             // TODO Auto-generated catch block
36             e.printStackTrace();
37         }finally{
38             if(out!=null){
39                 out.close();
40                 out=null;
41             }
42             if(in !=null){
43                 try {
44                     in.close();
45                 } catch (IOException e) {
46                     // TODO Auto-generated catch block
47                     e.printStackTrace();
48                 }
49                 in=null;
50             }
51             
52             if(socket!=null){
53                 try {
54                     socket.close();
55                 } catch (IOException e) {
56                     // TODO Auto-generated catch block
57                     e.printStackTrace();
58                 }
59             }
60         }
61     }
62 
63 }
View Code

 

 

【二】同步阻塞I/O服务端通信模型构造的伪异步通信模型

一:伪异步socket服务端启动(就是在同步的基础上使用了线程池)

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.IOException;
 4 import java.net.ServerSocket;
 5 import java.net.Socket;
 6 
 7 /**
 8  * 时间服务器
 9  * 基于同步阻塞I/O实现的服务器模型
10  * @author sxf
11  *
12  */
13 public class TimerServer {
14     
15     /**
16      * 启动timerServer服务器
17      */
18     public   void init(){
19         int port=8000;
20         //创建Socket服务
21         ServerSocket server=null;
22         try {
23             server=new ServerSocket(port);
24             System.out.println("TimerServer.init()===>the time server is start in port"+port);
25             Socket socket=null;
26             //创建处理socket请求的线程池
27             TimerServerHandlerExcetorPool pool=new TimerServerHandlerExcetorPool(50, 10000);
28             
29             while(true){
30                 //获取一次socket请求
31                 socket=server.accept();
32                 //将请求任务提交到线程池处理
33                 pool.execute(new TimerServerHandler(socket));
34             }
35         } catch (IOException e) {
36             e.printStackTrace();
37         }finally{
38             if(server!=null){
39                 try {
40                     server.close();
41                 } catch (IOException e) {
42                     // TODO Auto-generated catch block
43                     e.printStackTrace();
44                 }
45             }
46             server=null;
47         }
48         
49     }
50 
51     
52     public static void main(String[] args) {
53         //启动timerServer服务
54         TimerServer timerServer=new TimerServer();
55         timerServer.init();
56     }
57 }
View Code

二:伪异步socket服务处理socket请求的线程池

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.util.concurrent.ArrayBlockingQueue;
 4 import java.util.concurrent.ExecutorService;
 5 import java.util.concurrent.ThreadPoolExecutor;
 6 import java.util.concurrent.TimeUnit;
 7 /**
 8  * 处理socket服务器接收到的socket请求的线程池
 9  * @author sxf
10  *
11  */
12 public class TimerServerHandlerExcetorPool {
13 
14     private ExecutorService executorService;
15     
16     /**
17      * 初始化线程池
18      * @param maxPoolSize
19      * @param queueSize
20      */
21     public TimerServerHandlerExcetorPool(int maxPoolSize,int queueSize){
22         executorService=new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), maxPoolSize, 120L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize));
23     }
24     
25     /**
26      * 提交到线程池,执行socket请求任务
27      * @param runnable
28      */
29     public void execute(Runnable runnable){
30         executorService.execute(runnable);
31     }
32     
33 }
View Code

三:处理请求的Handler类(线程类)

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.io.PrintWriter;
 7 import java.net.Socket;
 8 import java.util.Date;
 9 
10 /**
11  * 时间服务器接受socket请求的处理类
12  * @author sxf
13  * 继承Runnable接口的线程类
14  *
15  */
16 public class TimerServerHandler implements Runnable {
17     
18     private Socket socket;
19 
20     public TimerServerHandler(Socket socket) {
21         this.socket=socket;
22     }
23     
24     /**
25      * 处理socket请求的线程体
26      */
27     @Override
28     public void run() {
29         BufferedReader in=null;
30         PrintWriter out=null;
31         try {
32             //获取请求的输入流
33             in=new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
34             //获取响应请求的输出流
35             out=new PrintWriter(this.socket.getOutputStream(),true);
36             
37             String currentTime=null;
38             String body=null;
39             //读取请求输入流的内容获取请求信息
40             while(true){
41                 body=in.readLine();
42                 if(body==null){
43                     break;
44                 }
45                 //打印请求信息
46                 System.out.println("TimerServerHandler.run()==>the time server receive order:"+body);
47                 
48                 //处理请求信息
49                 if("shangxiaofei".equals(body)){
50                     currentTime=new Date(System.currentTimeMillis()).toString();
51                 }else{
52                     currentTime="you is not get time";
53                 }
54                 //响应请求信息
55                 out.println(currentTime);
56             }
57             
58         } catch (IOException e) {
59             e.printStackTrace();
60         }finally{
61             if(in!=null){
62                 try {
63                     in.close();
64                 } catch (IOException e) {
65                     // TODO Auto-generated catch block
66                     e.printStackTrace();
67                 }
68             }
69             
70             if(out!=null){
71                 out.close();
72             }
73             
74             if(this.socket!=null){
75                 try {
76                     socket.close();
77                 } catch (IOException e) {
78                     // TODO Auto-generated catch block
79                     e.printStackTrace();
80                 }
81             }
82             
83             this.socket=null;
84         }
85         
86         
87         
88         
89     }
90 
91 }
View Code

四:客户端发送请求

 1 package com.yeepay.sxf.testbio;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.io.PrintWriter;
 7 import java.net.Socket;
 8 
 9 /**
10  * 创建一个客户端请求
11  * @author sxf
12  *
13  */
14 public class TimerClient {
15     
16     
17     
18     public static void main(String[] args) {
19         int port=8000;
20         Socket socket=null;
21         BufferedReader in=null;
22         PrintWriter out=null;
23         try {
24             socket=new Socket("127.0.0.1",port);
25             in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
26             out=new PrintWriter(socket.getOutputStream(),true);
27             //发送请求
28             out.println("shangxiaofei!=");
29             System.out.println("TimerClient.main()send order to server success");
30             
31             //等待服务器响应
32             String resp=in.readLine();
33             System.out.println("TimerClient.main(Now is:)"+resp);
34         } catch (Exception e) {
35             // TODO Auto-generated catch block
36             e.printStackTrace();
37         }finally{
38             if(out!=null){
39                 out.close();
40                 out=null;
41             }
42             if(in !=null){
43                 try {
44                     in.close();
45                 } catch (IOException e) {
46                     // TODO Auto-generated catch block
47                     e.printStackTrace();
48                 }
49                 in=null;
50             }
51             
52             if(socket!=null){
53                 try {
54                     socket.close();
55                 } catch (IOException e) {
56                     // TODO Auto-generated catch block
57                     e.printStackTrace();
58                 }
59             }
60         }
61     }
62 
63 }
View Code

 

相关文章
|
19天前
|
网络协议 Dubbo Java
一文搞懂NIO、AIO、BIO的核心区别(建议收藏)
本文详细解析了NIO、AIO、BIO的核心区别,NIO的三个核心概念,以及NIO在Java框架中的应用等。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
一文搞懂NIO、AIO、BIO的核心区别(建议收藏)
|
14天前
|
Java
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
51 9
|
2月前
|
存储 消息中间件 安全
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
【10月更文挑战第9天】本文介绍了如何利用JUC组件实现Java服务与硬件通过MQTT的同步通信(RRPC)。通过模拟MQTT通信流程,使用`LinkedBlockingQueue`作为消息队列,详细讲解了消息发送、接收及响应的同步处理机制,包括任务超时处理和内存泄漏的预防措施。文中还提供了具体的类设计和方法实现,帮助理解同步通信的内部工作原理。
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
|
2月前
|
Python
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
使用Python的socket库实现客户端到服务器端的图片传输,包括客户端和服务器端的代码实现,以及传输结果的展示。
145 3
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
|
2月前
|
JSON 数据格式 Python
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
本文介绍了如何使用Python的socket模块实现客户端到服务器端的文件传输,包括客户端发送文件信息和内容,服务器端接收并保存文件的完整过程。
158 1
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
|
1月前
|
Java 调度
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
2月前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
38 1
|
2月前
|
运维 Java Linux
【运维基础知识】Linux服务器下手写启停Java程序脚本start.sh stop.sh及详细说明
### 启动Java程序脚本 `start.sh` 此脚本用于启动一个Java程序,设置JVM字符集为GBK,最大堆内存为3000M,并将程序的日志输出到`output.log`文件中,同时在后台运行。 ### 停止Java程序脚本 `stop.sh` 此脚本用于停止指定名称的服务(如`QuoteServer`),通过查找并终止该服务的Java进程,输出操作结果以确认是否成功。
46 1
|
2月前
|
分布式计算 资源调度 Hadoop
大数据-01-基础环境搭建 超详细 Hadoop Java 环境变量 3节点云服务器 2C4G XML 集群配置 HDFS Yarn MapRedece
大数据-01-基础环境搭建 超详细 Hadoop Java 环境变量 3节点云服务器 2C4G XML 集群配置 HDFS Yarn MapRedece
82 4
|
2月前
|
Java Shell Maven
Flink-11 Flink Java 3分钟上手 打包Flink 提交任务至服务器执行 JobSubmit Maven打包Ja配置 maven-shade-plugin
Flink-11 Flink Java 3分钟上手 打包Flink 提交任务至服务器执行 JobSubmit Maven打包Ja配置 maven-shade-plugin
119 4