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

简介

早期的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. pytest--fixure前置执行一个函数

    import pytest@pytest.fixture()def login_r(): print('登陆') @pytest.fixture()def open_browser(): print( ...

  2. Kettle 中的循环

    说道循环,小伙伴们肯定不陌生,就是重复干一件事:而kettle中的循环一般是发生在job中,因为job是串行执行的: kettle的循环有两种,一种是通过js脚本,另外一种是通过遍历前面步骤返回的每一 ...

  3. linux 下格式化命令小记

    mkfs.ext4 /dev/sda1    # 格式化为ext4分区mkfs.ext3 /dev/sda1    # 格式化为ext3分区mkfs.ext2 /dev/sda1    # 格式化为e ...

  4. Mysql添加用户和数据库

    先创建数据库 创建用户并赋予一个数据库的所有权限 use mysql; create database databaseName character set utf8; grant all privi ...

  5. jq-demo-拖拽

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. Go 关系运算符

    Go 关系运算符 package main import "fmt" func main() { var a int = 21 var b int = 10 if( a == b ...

  7. 阿里云重磅推出物联网安全运营中心Link SOC

    阿里云IoT自主研发了新一代物联网安全平台Link Security,面向IoT设备全生命周期构建了一整套全链路多层次的安全防御体系,IoT物联网平台的业务在不同层面可以按需集成安全能力. 1.首先在 ...

  8. 作为互联网流量入口,CDN日志大数据你该怎么玩?

    CDN是非常重要的互联网基础设施,用户可以通过CDN,快速的访问网络中各种图片,视频等资源.在访问过程中,CDN会产生大量的日志数据,而随着如今越来越复杂的网络环境变化,和业务的迅速增长,日志数据变得 ...

  9. Python Django主机管理

    1.新建一个django project项目 django-admin startproject DjangoWeb 2.新建app python manage.py startapp master ...

  10. electron-vue中关闭烦人的es语法检查

    本项目环境是 electron-vue搭建的项目,项目结构根vue-cli创建的项目结构稍微有所不同 主要修改的地方有3个 把这3个文件里面的以下代码全部删掉 { test: /\.(js)$/, e ...