BIO 详解
调用者主动等待调用的结果
简介
早期的jdk中,采用BIO通信模式:
通常有一个acceptor(消费者) 去负责监听客户端的连接。
它接收到客户端的连接请求之后为每个客户端创建一个线程进行链路处理,处理完成之后,线程销毁。
一个客户端连接,对应一个处理线程。他们之间的对应关系是 1:1。
由于客户端连接和服务端的处理之间的对应关系是1:1,如果遇到任务比较大,处理比较慢。
或者并发量比较大的情况下,系统会创建大量的线程。从而导致服务器线程暴增,性能急剧下降,甚至宕机。

客户端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
Socket socket = null;
BufferedReader in = null;
PrintWriter out = null;
try {
//创建连接
socket = new Socket("127.0.0.1", 8080);
//输出流:发送数据
out = new PrintWriter(socket.getOutputStream(), true);
out.println("发送数据");
//输入流:接收数据
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//阻塞:未收到数据就等在这里
String resp = in.readLine();
System.out.println("回应:" + resp);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
out.close();
out = null;
}
}
}
服务端
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
//创建服务端
serverSocket = new ServerSocket(8080);
Socket socket = null;
while (true) {
//从socket的队列中获取socket的连接
//相当于一个消费者
///当前的线程阻塞在accept方法上面。该方法一直阻塞,除非获取到socket连接返回
socket = serverSocket.accept();
// 获得到socket连接之后,分配线程任务进行处理
new Thread(new Handler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
serverSocket = null;
}
}
}
}
处理线程
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
//输入流:接收数据
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
//接收数据
String receive = null;
//输出流:发送数据
out = new PrintWriter(this.socket.getOutputStream(), true);
//回应结果
String currentTime = null;
while (true) {
//输入流:读取数据的部分是阻塞的
//由于使用的是阻塞IO,那么read方法一直处于阻塞状态,要等到数据传送完成才结束(返回-1)
//1,内核程序从网卡中把数据读取到内核空间中,是一直阻塞的。
//2,用户程序把内核空间的数据复制到用户空间的过程,是阻塞的。
//这两个过程中,对应的程序部分就是read方法的阻塞
receive = in.readLine();
if (receive == null) {
break;
}
System.out.println(receive);
//输出流:输出数据
currentTime = "收到";
out.println(currentTime);
}
} catch (IOException e) {
e.printStackTrace();
if (in != null) {
try {
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (out != null) {
out.close();
out = null;
}
}
}
}
BIO 详解的更多相关文章
- redis BIO详解
BIO即background I/O service,后台I/O服务,是redis的aof持久化后台服务. redis把阻塞的同步I/O操作交给后台I/O服务来完成:close和fsync. clos ...
- 详解tomcat的连接数与线程池
前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在前面的文章 详解Tomcat配置文件server.xm ...
- 详解Tomcat的连接数和线程池
转: https://www.cnblogs.com/kismetv/p/7806063.html#t11 前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须 ...
- Tomcat记录-tomcat常用配置详解和优化方法(转载)
常用配置详解 1 目录结构 /bin:脚本文件目录. /common/lib:存放所有web项目都可以访问的公共jar包(使用Common类加载器加载). /conf:存放配置文件,最重要的是serv ...
- Python 19 Django 详解
本节概要 Django详解 前言 有一部分原因是,确实djando的课程有点多:并且,最近又在研究利用python做数据分析时间上耽误了.所以楼主讲所有的课程全部重新观看了一遍,再来撰写博客,其实说起 ...
- 详解 Tomcat 的连接数与线程池
前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在前面的文章 详解Tomcat配置文件server. ...
- Java性能分析之线程栈详解与性能分析
Java性能分析之线程栈详解 Java性能分析迈不过去的一个关键点是线程栈,新的性能班级也讲到了JVM这一块,所以本篇文章对线程栈进行基础知识普及以及如何对线程栈进行性能分析. 基本概念 线程堆栈也称 ...
- 详解tomcat连接数和线程数
前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在前面的文章 详解Tomcat配置文件server.xm ...
- Java网络编程和NIO详解3:IO模型与Java网络编程模型
Java网络编程和NIO详解3:IO模型与Java网络编程模型 基本概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32 ...
随机推荐
- 2-Ubuntu命令安装mysql服务器和客户端及安装后的简单验证操作
转自: https://www.cnblogs.com/zhuyp1015/p/3561470.html 安装完成之后可以使用如下命令来检查是否安装成功: sudo netstat -tap | ...
- dnslog小技巧
一.dnslog利用场景 主要针对无回显的情况. Sql-Blind RCE SSRF RFI(Remote File Inclusion) 二.原理 将dnslog平台中的特有字段payload带入 ...
- 三.Python数据类型详述
Python第三节数据类型详述 一.多变量赋值 python允许多变量赋值 多变量赋相同的值a = b = c = 1 多变量赋不同的值a, b, c = 1, 2, "fuckyou&qu ...
- 内网端口转发[SSH]
一.应用场景 获取到目标边界机器linux服务器一台,想继而向内网其他机器渗透,获取到一台webshell发现处于内网当中且不通外网.可以通过linux ssh隧道对目标内网机器进行访问. 二.利用手 ...
- 读书笔记二、ndarray的数据类型
dtype(数据类型)是一个特殊的对象,它含有ndarray将一块内存解释为特定数据类型所需的信息: import numpy as np arr1=np.array([1,2,3],dtype=np ...
- Spring常见面试题及答案解析
.说一下spring中Bean的作用域 singleton: Spring IoC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象.Singleton作用域是Spri ...
- JS实现菜单滚动到一定高度后固定
在有些网页中我们会发现会有这样的现象:某个div会随着屏幕的滚动达到一定高度的时候位置就固定下来了.例如一下导航条: 那么这里就需要用到JS的逻辑方法来实现了. html <div id=&qu ...
- JavaScript ---- 闭包(什么是闭包,为什么使用闭包,闭包的作用)
经常被问到什么是闭包? 说实话闭包这个概念很难解释.JavaScript权威指南里有这么一段话:“JavaScript函数是将要执行的代码以及执行这些代码作用域构成的一个综合体.在计算机学术语里,这种 ...
- charles抓取数据
charles抓包 抓取手机app的数据 charles设置 help--->SSL Proxying--->Install Charles Root Certificate 1.给电脑下 ...
- Android Studio 安装及汉化
{ https://www.bilibili.com/video/av48649403?from=search&seid=15739157224002905777 Tool: https:// ...