漫谈Java IO之普通IO流与BIO服务器

今天来复习一下基础IO,也就是最普通的IO。

  1. 网络IO的基本知识与概念
  2. 普通IO以及BIO服务器
  3. NIO的使用与服务器Hello world
  4. Netty入门与服务器Hello world
  5. Netty深入浅出

输入流与输出流

Java的输入流和输出流,按照输入输出的单元不同,又可以分为字节流和字符流的。

JDK提供了很多输入流和输出流,比如:

字节流可以按照不同的变量类型进行读写,而字符流则是基于字符编码的。不同的字符编码包含的字节数是不一样的,因此在使用字符流时,一定要注意编码的问题。

读写

字节的输入输出流操作

// 字节输入流操作
InputStream input = new ByteArrayInputStream("abcd".getBytes());
int data = input.read();
while(data != -1){
    System.out.println((char)data);
    data = input.read();
}

// 字节输出流
ByteArrayOutputStream output = new ByteArrayOutputStream();
output.write("12345".getBytes());
byte[] ob = output.toByteArray();

字符的输入输出流操作

// 字符输入流操作
Reader reader = new CharArrayReader("abcd".toCharArray());
data = reader.read();
while(data != -1){
    System.out.println((char)data);
    data = reader.read();
}
// 字符输出流
CharArrayWriter writer = new CharArrayWriter();
writer.write("12345".toCharArray());
char[] wc = writer.toCharArray();

关闭流

流打开后,相当于占用了一个文件的资源,需要及时的释放。传统的标准关闭的方式为:

// 字节输入流操作
InputStream input = null;
try {
    input = new ByteArrayInputStream("abcd".getBytes());
    int data = input.read();
    while (data != -1) {
        System.out.println((char) data);
        // todo
        data = input.read();
    }
}catch(Exception e){
    // todo
}finally {
    if(input != null) {
        try {
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在JDK1.7后引入了try-with-resources的语法,可以在跳出try{}的时候直接自动释放:

try(InputStream input1 = new ByteArrayInputStream("abcd".getBytes())){
   //

}catch (Exception e){
    //
}

IOUtils

直接使用IO的API还是很麻烦的,网上的大多数教程都是各种while循环,操作很麻烦。其实apache common已经提供了一个工具类——IOUtils,可以方便的进行IO操作。

比如IOUtils.readLines(is, Charset.forName("UTF-8"));可以方便的按照一行一行读取.

BIO阻塞服务器

基于原始的IO和Socket就可以编写一个最基本的BIO服务器。

概要: 这个模型很简单,就是主线程(Acceptor)负责接收连接,然后开启新的线程专门负责连接处理客户端的请求。


import io.netty.util.CharsetUtil;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class PlainOioServer {
    public void serve(int port) throws IOException {
        // 开启Socket服务器,并监听端口
        final ServerSocket socket = new ServerSocket(port);
        try{
            for(;;){
                // 轮训接收监听
                final Socket clientSocket = socket.accept();
                try {
                    Thread.sleep(500000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("accepted connection from "+clientSocket);
                // 创建新线程处理请求
                new Thread(()->{
                   OutputStream out;
                   try{
                       out = clientSocket.getOutputStream();
                       out.write("Hi\r\n".getBytes(CharsetUtil.UTF_8));
                       out.flush();
                   } catch (IOException e) {
                       e.printStackTrace();
                   } finally {
                       try{
                           clientSocket.close();
                       } catch (IOException e) {
                           e.printStackTrace();
                       }
                   }
                }).start();
            }
        } catch (IOException e){
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws IOException {
        PlainOioServer server = new PlainOioServer();
        server.serve(5555);
    }
}

然后执行telnet localhost 5555,就能看到返回结果了。

这种阻塞模式的服务器,原理上很简单,问题也容易就暴露出来:

  1. 服务端与客户端的连接相当于1:1,因此如果连接数上升,服务器的压力会很大
  2. 如果主线程Acceptor阻塞,那么整个服务器将会阻塞,单点问题严重
  3. 线程数膨胀后,整个服务器性能都会下降

改进的方式可以基于线程池或者消息队列,不过也存在一些问题:

  1. 线程池的数量、消息队列后端服务器并发处理数,都是并发数的限制
  2. 仍然存在Acceptor的单点阻塞问题

接下来,将会介绍基于Nio的非阻塞服务器模式,如果忘记什么是IO多路复用,可以回顾前面一篇分享。敬请期待吧...

原文地址:https://www.cnblogs.com/xing901022/p/8666147.html

时间: 2024-08-28 17:55:01

漫谈Java IO之普通IO流与BIO服务器的相关文章

java(九)IO流

IO流: IO流是用来处理设备之间的数据传输的. java对数据的操作是通过流的方式. java用于操作流的对象都在IO包中. 流按操作的数据分为两种:字符流和字节流. 字符流的由来:字符流其实就是字节流读取文字字节数据后,不直接操作而是先查指定的编码表,  获取对应的文字.再对这个文字进行操作. 简单说,就是字符流=字节流+编码表. 字节流的抽象基类(就是顶层父类):InputStream,OutputStream 字符流的抽象基类:Reader,Writer 这些体系的子类都以父类名作为后缀

java之IO其它类型的流

一.操作基本数据类型的流 DataInputStream DataOutputStream 数据输出流允许应用程序以适当方式将基本java数据类型写入输出流中.然后,应用程序可以使用数据输入流将数据读入. package a; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import

Java nio 笔记:系统IO、缓冲区、流IO、socket通道

一.Java IO 和 系统 IO 不匹配 在大多数情况下,Java 应用程序并非真的受着 I/O 的束缚.操作系统并非不能快速传送数据,让 Java 有事可做:相反,是 JVM 自身在 I/O 方面效率欠佳.操作系统与 Java 基于流的 I/O模型有些不匹配.操作系统要移动的是大块数据(缓冲区),这往往是在硬件直接存储器存取(DMA)的协助下完成的.而 JVM 的 I/O 操作类喜欢操作小块数据--单个字节.几行文本.结果,操作系统送来整缓冲区的数据,java.io 包的流数据类再花大量时间

Java IO 字节流与字符流 (二)

概述 IO流用来处理设备之间的数据传输 Java对数据的操作时通过流的方式 Java用于操作流的对象都在IO包中 流按操作的数据分为:字节流和字符流 流按流向不同分为:输入流和输出流 IO流常用基类 字节流的抽象基类 InputStream,OuputStream 字符流的抽象基类 Reader,Writer 注: 这些基类的子类都是以基类的名称结尾的,如FileReader,FileInputStream 字节流 字节流:以字符为导向的流 简单介绍一个例子,演示字节流对图片的复制 1: imp

JavaLearning:JAVA IO 之内存操作流

package org.fun.io; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; public class ByteArrayDemo { public static void main(String[] args) { String str = "helloworld";// 定义字符串,全部由小写字母组成 ByteArrayOutputStream bos = null;//

Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)

声明:该博文以socket中,关闭输出流为例进行说明. 为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutputStream(mySocket.getOutputStream()));中的dout做为Socket输出流的代言.同样的,din是输入流的代言. 可以造成dout被关闭的操作有: 1.调用dout.close();或din.close();因为使用这种流关闭,会造成socket被关闭,所以输入输出

java之十 高级IO流

java.io定义的输入/输出类列于下表: ObjectInputStream.GetField和ObjectOutputStream.PutField是Java2新添的内部类. java.io包还包含两个不受java2欢迎的类,这两个类没有在上表中列出:LineNumberInputStream和StringBufferInputStream.新代码不应该使用两个类. 下面是由java.io定义的接口: FileFilter接口是Java2新增的. java.io包中有很多类和接口.包括字节和

漫谈Java IO之 NIO那些事儿

前面一篇中已经介绍了基本IO的使用以及最简单的阻塞服务器的例子,本篇就来介绍下NIO的相关内容,前面的分享可以参考目录: 网络IO的基本知识与概念 普通IO以及BIO服务器 NIO的使用与服务器Hello world Netty入门与服务器Hello world Netty深入浅出 NIO,也叫做new-IO或者non-blocking-IO,就暂且理解为非阻塞IO吧. 为什么选择NIO 那么NIO相对于IO来说,有什么优势呢?总结来说: IO是面向流的,数据只能从一端读取到另一端,不能随意读写

java知识点分享,IO流详解!

Java知识IO流详解有人觉得IO知识不太重要,其实不然,IO的使用范围很广,最能体现IO价值的就是网络上的数据传递,尤其是进入互联网时代后,各种常见的分布式架构,都少不了IO的体现.并且很多大厂的面试题中都会体现出对IO的重视,包括衍生出来的NIO.序列化等等.因此学好IO,变成了一件很重要的事情.IO基本概念IO可以简单的理解成INPUT和OUT,代表输入输出的意思.输入就是读,输出就是写.IO可以读写硬盘.光盘.内存.键盘.网络等资源上的数据.流IO中的流就相当于现实生活中的水流一样,一打