在实际的工作开发中,传统的模型有client/service模型。client端和service端要进行通信的话,有一种套接字的方式。传统的socket编程,包含一个socket服务端和一到多个socket客户端。在连接过程中,sokcetServer 绑定一个端口进行监听。client端通过ip地址和端口号对服务进行访问。在服务进入到service端后,service端新建一个线程。线程对请求进行相应的处理,处理完毕后,将处理结果返回给client端。在处理过程中,连接client阻塞。

  代码实现:

  server端代码:

  Server 类

  ServerHandler类,业务处理类

  client端代码:

  Client类

  优点:传统的BIO模型进行通信,代码可读性比较强,理解容易。运行中,server端通过主线程监听accpet()方法阻塞式获取server的消息。

  缺点:该模型最大的问题是,每一个client端访问都对应一个后台的线程,使得系统不具备弹性伸缩能力。一旦client请求过多,线程数会迅速膨胀,系统性能会急剧下降,导致堆栈溢出,进程宕机等问题的发生。

  为了改进线程数过多,导致系统宕机的问题,同时也为了解决创建线程的消耗问题。后来又演进出了一种通过线程池或者消息队列实现1个或者多个线程处理N个客户端的模型,由于它的底层通信机制依然使用同步阻塞IO,所以被称为 “伪异步”。其原理就是在原来的service上新增一个线程池,将处理业务的线程通过线程池进行管理。如果线程数量到达上限时,将请求先存入queue中进行缓冲。具体代码如下:

  client端代码不变。

  server端:  

 1 import java.io.BufferedReader;
2 import java.io.PrintWriter;
3 import java.net.ServerSocket;
4 import java.net.Socket;
5
6 public class Server {
7
8 final static int PORT = 8765;
9
10 public static void main(String[] args) {
11 ServerSocket server = null;
12 BufferedReader in = null;
13 PrintWriter out = null;
14 try {
15 server = new ServerSocket(PORT);
16 System.out.println("server start");
17 Socket socket = null;
18 HandlerExecutorPool executorPool = new HandlerExecutorPool(50, 50);
19 while(true){
20 socket = server.accept();
21
22 executorPool.execute(new ServerHandler(socket));
23
24 }
25
26 } catch (Exception e) {
27 e.printStackTrace();
28 } finally {
29 if(in != null){
30 try {
31 in.close();
32 } catch (Exception e1) {
33 e1.printStackTrace();
34 }
35 }
36 if(out != null){
37 try {
38 out.close();
39 } catch (Exception e2) {
40 e2.printStackTrace();
41 }
42 }
43 if(server != null){
44 try {
45 server.close();
46 } catch (Exception e3) {
47 e3.printStackTrace();
48 }
49 }
50 server = null;
51 }
52
53
54
55 }
56
57
58 }

Server类

 1 import java.util.concurrent.ArrayBlockingQueue;
2 import java.util.concurrent.ThreadPoolExecutor;
3 import java.util.concurrent.TimeUnit;
4
5
6 public class HandlerExecutorPool {
7 private ArrayBlockingQueue queue ;
8 private ThreadPoolExecutor executor;
9 public HandlerExecutorPool(int maxPoolSize, int queueSize){
10 queue = new ArrayBlockingQueue<Runnable>(queueSize);
11 this.executor = new ThreadPoolExecutor(
12 5,
13 maxPoolSize,
14 120L,
15 TimeUnit.SECONDS,
16 queue);
17 }
18
19 public void execute(Runnable task){
20 System.out.println("corePoolSize== "+executor.getCorePoolSize());
21 System.out.println("queuesize=="+queue.size());
22 this.executor.execute(task);
23
24 System.out.println("当前运行线程== "+executor.getLargestPoolSize());
25 System.out.println("queuesize=="+queue.size());
26 }
27
28
29
30 }

HandlerExecutorPool 线程池缓冲队列类

 1 import java.io.BufferedReader;
2 import java.io.InputStreamReader;
3 import java.io.PrintWriter;
4 import java.net.Socket;
5 import java.util.concurrent.TimeUnit;
6
7 public class ServerHandler implements Runnable {
8
9 private Socket socket;
10 public ServerHandler (Socket socket){
11 this.socket = socket;
12 }
13
14 @Override
15 public void run() {
16 BufferedReader in = null;
17 PrintWriter out = null;
18 try {
19 Thread.currentThread().sleep(1000);
20 in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
21 out = new PrintWriter(this.socket.getOutputStream(), true);
22 String body = null;
23 while(true){
24 body = in.readLine();
25 if(body == null) break;
26 System.out.println("Server:" + body);
27 out.println("Server response");
28 }
29 } catch (Exception e) {
30 e.printStackTrace();
31 } finally {
32 if(in != null){
33 try {
34 in.close();
35 } catch (Exception e1) {
36 e1.printStackTrace();
37 }
38 }
39 if(out != null){
40 try {
41 out.close();
42 } catch (Exception e2) {
43 e2.printStackTrace();
44 }
45 }
46 if(socket != null){
47 try {
48 socket.close();
49 } catch (Exception e3) {
50 e3.printStackTrace();
51 }
52 }
53 socket = null;
54 }
55
56
57 }
58
59 }

ServerHandler类,业务处理类

  这样改造后,有效的缓解了server端线程数过多时宕机的问题,但是依然没有解决阻塞的问题。依然会出现请求过多时,前台等待超时的问题。

BIO编程的更多相关文章

  1. Java IO编程全解(二)——传统的BIO编程

    前面讲到:Java IO编程全解(一)——Java的I/O演进之路 网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口 ...

  2. 深入学习Netty(1)——传统BIO编程

    前言 之前看过Dubbo源码,Nacos等源码都涉及到了Netty,虽然遇到的时候查查资料,后面自己也有私下学习Netty并实践,但始终没有形成良好的知识体系,Netty对想要在Java开发上不断深入 ...

  3. JDK BIO编程

    网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起连接请求,通过三次握手建 ...

  4. netty学习(二)--传统的bio编程

    网络编程的基本模型是Client/Server模型.也就是两个进程之间进行相互通信,当中服务端提供位置信息( 绑定ip地址和监听port),client通过连接操作向服务端监听的地址发送连接请求,通过 ...

  5. bio编程示例

    直接干代码,用BIO写一个Server端,然后使用telnet模拟客户端发送数据 import java.io.IOException; import java.io.InputStream; imp ...

  6. (转)Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    原文出自:http://blog.csdn.net/anxpp/article/details/51512200 1.BIO编程 1.1.传统的BIO编程 网络编程的基本模型是C/S模型,即两个进程间 ...

  7. Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解. 下面代码中会使用这样一个例子:客户端发送一段算式的字符串到服务器,服务器计算后返回结果到客户端. 代码的所有说明,都直接作为 ...

  8. io编程,bio,nio,aio

    本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解. 下面代码中会使用这样一个例子:客户端发送一段算式的字符串到服务器,服务器计算后返回结果到客户端. 代码的所有说明,都直接作为 ...

  9. hadoop---Java 网络IO编程总结BIO、NIO、AIO

    转载请注明出处:http://blog.csdn.net/anxpp/article/details/51512200,谢谢! 本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解 ...

随机推荐

  1. 刷题[NPUCTF2020]ezlogin

    xpath注入 xpath注入这篇文章有关于xpath很详细的解答,包括原理等,详细了解请见此篇. 我个人再稍微讲一讲: 首先它的网站目录下会有一个xml文件,大概格式是这样: <?xml ve ...

  2. Linux的MySQL安装方法

    第一种: APT方式安装 在ubuntu系统的apt软件仓库中,默认存在MySQL数据库 在用户模式下使用命令:  apt/apt-get install mysql-server mysql-cli ...

  3. DevOps Next-AI / ML虚拟会议

    这个中秋国庆,一起进阶反超呀!10月1日星期四,加入DevOps Next,可以参加有关AI和ML的免费活动,内容涉及持续测试,代码质量和DevOps生产力.优秀的你一起来加入! 关于本次活动 Dev ...

  4. NMAP类型题目 (escapeshellarg,escapeshellcmd使用不当)

    [BUUCTF 2018]Online Tool 给出了源码 审计 <?php if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $_SERVER[' ...

  5. 在 Kubernetes 上部署 OpenStack 是什么体验

    红蓝出 CP,OpenStack 和 Kubernetes 在一起会怎样? 背景 从去年开始就想深入地学习 Kubernetes,首先想到是在 OpenStack 上能比较轻松地玩转,所以去 尝试了 ...

  6. Go-简介

    Go简介 Google开发,新的具有面向接口.函数式编程.并发编程特点的编译性强类型通用编程语言 Go核心 1. 接口 2. 并发编程 3. 函数 Go-接口 package main import ...

  7. # mac使用homebrew安装jdk和tomcat

    homebrew安装jdk 前提是已经安装homebrew //直接命令行安装 brew cask install homebrew/cask-versions/adoptopenjdk8 homeb ...

  8. notepad快捷使用

    1.快捷键 参考:https://www.php.cn/tool/notepad/428638.html notepad++是经常使用的一款编辑器软件,在编辑特殊文本的时候(html,java...) ...

  9. 9.13 考试 T2 区间

    删区间 题意: 给出一个长度为

  10. 设备通讯——RS232

    RS232的接口有两种--一种公头.一种母头,两种头的引脚是有区别的 MAX232电路图: 注意:串口通讯需要交叉接线.