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 ...
随机推荐
- gary's mod
第一题: class Parent(object): x = 1 class Child1(Parent): pass class Child2(Parent): pass print(Parent. ...
- Jmeter 请求参数中包含 MD5 加密的密码
如何在jmeter中对参数进行加密 使用工具:java+myeclipse 让开发将他的加密类从eclipse中导出来打成jar包,放在jmeter安装文件夹lib文件夹中%JMETER HOME%\ ...
- EE5111_A0206839W
EE5111 Selected Topics in Industrial Control & Instrumentation Assessment: Implement a simple ...
- 2019-4-12-WPF-类型的构造函数执行符合指定的绑定约束的调用时引发了异常
title author date CreateTime categories WPF 类型的构造函数执行符合指定的绑定约束的调用时引发了异常 lindexi 2019-04-12 08:52:35 ...
- pandas-append()
DataFrame.append(self,other,ignore_index = False,verify_integrity = False,sort = Nore) 作用是将其他对象附加到调用 ...
- 关于mybaitis
mybatis启动流程 1.首先来看看最简单的mybatis项目启动过程 public static void mybatisTest() throws IOException { String re ...
- python编程学习day04
1.函数名是变量名 “=”是内存指向,等号赋值操作,内存指向操作 变量——可赋值,可作为列表元素 函数名可以作为返回值返回 函数名可作为参数传递 2.闭包 内层函数使用了外层函数的变量 作用:可以让一 ...
- canvas画布导出图片并下载
近期在学习关于画布知识,关于 画布导出图片, 在导出jpeg格式的图片时,会发现图片背景色变成了黑色,原因是画布透明的地方 默认转成了黑色,可以在绘制画布前设置透明处背景色为白色. // 背景色转换成 ...
- NX二次开发-UFUN打开信息窗口UF_UI_open_listing_window()
NX9+VS2012 #include <uf.h> #include <uf_ui.h> UF_initialize(); //方法1(uc1601) uc1601();// ...
- hibernate 一对多查询 对多的一方进行分页
//查询用户留言@Overridepublic List<LeaveWords> getLeaveWords(String userName) {Session session = nul ...