首页 > 编程语言 > 详细

JAVA BIO 编程

时间:2020-05-04 01:11:33      阅读:67      评论:0      收藏:0      [点我收藏+]

1.IO模型,首先对Java网络编程的发展流程回顾一下,最开始的TCP/IP服务器,Java原生IO,到后面的BIO,最后是Netty。

技术分享图片

 

2.Java 共支持 3 种网络编程模型/IO 模式: BIO、 NIO、 AIO

 Java BIO : 同步并阻塞(传统阻塞型), 服务器实现模式为一个连接一个线程, 即客户端有连接请求时服务器
端就需要启动一个线程进行处理, 如果这个连接不做任何事情会造成不必要的线程开销。

技术分享图片

 

 

 3.Java NIO : 同步非阻塞, 服务器实现模式为一个线程处理多个请求(连接), 即客户端发送的连接请求都会注
册到多路复用器上, 多路复用器轮询到连接有 I/O 请求就进行处理 【简单示意图】

技术分享图片

 

 

 4.Java AIO(NIO.2) : 异步非阻塞, AIO 引入异步通道的概念, 采用了 Proactor 模式, 简化了程序编写, 有效
的请求才启动线程, 它的特点是先由操作系统完成后才通知服务端程序启动线程去处理, 一般适用于连接数较
多且连接时间较长的应用     


 对 BIO 编程流程的梳理

1) 服务器端启动一个 ServerSocket。
2) 客户端启动 Socket 对服务器进行通信, 默认情况下服务器端需要对每个客户 建立一个线程与之通讯。
3) 客户端发出请求后, 先咨询服务器是否有线程响应, 如果没有则会等待, 或者被拒绝。
4) 如果有响应, 客户端线程会等待请求结束后, 在继续执行 。
代码:

技术分享图片
package com.atguigu.bio;

import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BIOServer {
    public static void main(String[] args) throws Exception {

        //线程池机制

        //思路
        //1. 创建一个线程池
        //2. 如果有客户端连接,就创建一个线程,与之通讯(单独写一个方法)

        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();

        //创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(6666);

        System.out.println("服务器启动了");

        while (true) {

            System.out.println("线程信息 id =" + Thread.currentThread().getId() + " 名字=" + Thread.currentThread().getName());
            //监听,等待客户端连接
            System.out.println("等待连接....");
            final Socket socket = serverSocket.accept();
            System.out.println("连接到一个客户端");

            //就创建一个线程,与之通讯(单独写一个方法)
            newCachedThreadPool.execute(new Runnable() {
                public void run() { //我们重写
                    //可以和客户端通讯
                    handler(socket);
                }
            });

        }


    }

    //编写一个handler方法,和客户端通讯
    public static void handler(Socket socket) {

        try {
            System.out.println("线程信息 id =" + Thread.currentThread().getId() + " 名字=" + Thread.currentThread().getName());
            byte[] bytes = new byte[1024];
            //通过socket 获取输入流
            InputStream inputStream = socket.getInputStream();

            //循环的读取客户端发送的数据
            while (true) {

                System.out.println("线程信息 id =" + Thread.currentThread().getId() + " 名字=" + Thread.currentThread().getName());

                System.out.println("read....");
               int read =  inputStream.read(bytes);
               if(read != -1) {
                   System.out.println(new String(bytes, 0, read
                   )); //输出客户端发送的数据
               } else {
                   break;
               }
            }


        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println("关闭和client的连接");
            try {
                socket.close();
            }catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}
View Code

 

 java BIO 问题分析
1) 每个请求都需要创建独立的线程, 与对应的客户端进行数据 Read, 业务处理, 数据 Write 。
2) 当并发数较大时, 需要创建大量线程来处理连接, 系统资源占用较大。
3) 连接建立后, 如果当前线程暂时没有数据可读, 则线程就阻塞在 Read 操作上, 造成线程资源浪费



 

JAVA BIO 编程

原文:https://www.cnblogs.com/cb1186512739/p/12773500.html

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!