调用者主动等待调用的结果

简介

早期的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 详解的更多相关文章

  1. redis BIO详解

    BIO即background I/O service,后台I/O服务,是redis的aof持久化后台服务. redis把阻塞的同步I/O操作交给后台I/O服务来完成:close和fsync. clos ...

  2. 详解tomcat的连接数与线程池

    前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在前面的文章 详解Tomcat配置文件server.xm ...

  3. 详解Tomcat的连接数和线程池

    转: https://www.cnblogs.com/kismetv/p/7806063.html#t11 前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须 ...

  4. Tomcat记录-tomcat常用配置详解和优化方法(转载)

    常用配置详解 1 目录结构 /bin:脚本文件目录. /common/lib:存放所有web项目都可以访问的公共jar包(使用Common类加载器加载). /conf:存放配置文件,最重要的是serv ...

  5. Python 19 Django 详解

    本节概要 Django详解 前言 有一部分原因是,确实djando的课程有点多:并且,最近又在研究利用python做数据分析时间上耽误了.所以楼主讲所有的课程全部重新观看了一遍,再来撰写博客,其实说起 ...

  6. 详解 Tomcat 的连接数与线程池

      前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在前面的文章 详解Tomcat配置文件server. ...

  7. Java性能分析之线程栈详解与性能分析

    Java性能分析之线程栈详解 Java性能分析迈不过去的一个关键点是线程栈,新的性能班级也讲到了JVM这一块,所以本篇文章对线程栈进行基础知识普及以及如何对线程栈进行性能分析. 基本概念 线程堆栈也称 ...

  8. 详解tomcat连接数和线程数

    前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在前面的文章 详解Tomcat配置文件server.xm ...

  9. Java网络编程和NIO详解3:IO模型与Java网络编程模型

    Java网络编程和NIO详解3:IO模型与Java网络编程模型 基本概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32 ...

随机推荐

  1. el-scrollbar 如何去掉横线滚动条?

    1. el-scrollbar style="height:100%" 2. 不要在scoped私有变量添加 .el-scrollbar__wrap{ overflow-x: hi ...

  2. sublime里面几个个人觉得比较实用的快捷键

    Alt+F3 选中文本按下快捷键,即可一次性选择全部的相同文本进行同时编辑.举个栗子:快速选中并更改所有相同的变量名.函数名等. Ctrl+L 选中整行,继续操作则继续选择下一行,效果和 Shift+ ...

  3. mongo之$group+$addToSet

    直接举例说明 #ArrangingResult表结构 { "_id" : ObjectId("5acc739df78bf21f8c94f080"), " ...

  4. BBS论坛 后台管理

    七.后台管理 后台管理页面: <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  5. Java调用Linux下的shell命令并将结果以流的形式返回

    import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader; public cl ...

  6. Spring入门(四)Spring-test模块

    自动化转配bean的测试案例分析 package soundsystem; import static org.junit.Assert.*; import org.junit.Rule; impor ...

  7. -bash: docker-compose: command not found、linux 安装 docker-compose

    方式1:https://blog.csdn.net/qq_32447321/article/details/76512137 方式2: curl -L https://get.daocloud.io/ ...

  8. leetcood学习笔记-70-爬楼梯

    题目描述: 第一次提交:(超时) class Solution: def climbStairs(self, n: int) -> int: if n == 0 or n == 1 or n = ...

  9. bzoj1012题解

    [解题思路] 强制在线线段树/树状数组,没什么好说的..复杂度O(mlog2m)(线段树)或O(mlog22m)(树状数组). [参考代码] (还naive的时候写的zkw真是翔..) #includ ...

  10. delphi windows操作

    输入 procedure TypeKeyString(s: string); var c: Char; i: integer; off: integer; vkw: Word; begin to Le ...