从NIO到netty(1) 传统IO和装饰器模式/ NIO简介

jdk 1.4之前用的都是传统IO,主要是基于Stream的IO体系,是面相流的变成,java中一个流要么是输入流,要么是输出流。不能同时既是输入流又是输出流

关于io的详细说明,可以参考这篇文章https://www.cnblogs.com/ylspace/p/8128112.html

这里提及一下装饰器模式

在java.io中大量使用装饰器模式,这里介绍下装饰器模式

装饰器模式中的角色有:

1、抽象构件角色

给出一个抽象接口,以规范准备接受附加责任的对象

2、具体构件角色

定义一个将要接受附加责任的类

3、装饰角色

持有一个构建对象的实例,并定义一个与抽象构件接口一致的接口

4、具体装饰角色

负责给构建对象贴上附加的责任

举一个简单例子

1.有一批奔驰汽车,共同的特点就是豪华车

2.不同的型号的奔驰都有各自的特点,比如S级奔驰自带柏林之声音响,AMG奔驰高性能等

定义一个奔驰车子接口

public interface Benz {

    public void descript();
    
}

定义一个奔驰通用模型

public class MecidesBenzCar implements Benz {

    @Override
    public void descript() {
        System.out.println("奔驰豪华车");
    }
    
}

定义一个装饰器角色,具体的工作具体装饰器去实现,这样,比如S级奔驰有柏林环绕声 AMG奔驰高性能,这两个动作就可以做到复用,装饰器角色定义为FilterBenz:

public abstract class FilterBenz implements Benz {

    protected Benz benz;
    
}

接下去就是实现具体的

public class BenzSClass extends FilterBenz {
    
    public BenzSClass(Benz benz) {
        this.benz = benz;
    }
    
   public void descript() {
  System.out.println("有柏林环绕声");
  benz.descript();
} 
}

public class BenzAMGClass extends FilterBenz {

public BenzSClass(Benz benz) { this.benz = benz; } public void descript() {
System.out.println("高性能车");
  benz.descript();
}

如果我要得到一个S级奔驰的描述

Benz benz =  new BenzSClass(new MecidesBenzCar());--------1

如果我要得到一个AMG奔驰的描述

Benz benz =  new BenzAMGClass(new MecidesBenzCar());---------2

如果我要得到一个S级奔驰AMG的描述

Benz benz =  new BenzSClass(new BenzAMGClass(new MecidesBenzCar()));----------3

--------------

上述代码是不是很熟悉,

BufferedReader br = new BufferedReader(new
    InputStreamReader(System.in)); 这是我们用于读取的常见动作

在java的io体系中大量使用了装饰器模式

盗用一张图

从NIO到netty(1) 传统IO和装饰器模式/ NIO简介_第1张图片

 

传统IO体系中有四个基础接口,类似于上述的Benz接口

以Reader接口为例:

FitlerReader对应了MecidesBenzCar

PushbackReader就是对应了BenzSClass

--------------------------------------

JDK1.4之后引入了nio,可以理解成new io也可以理解成non-blocking io。

NIO有三个核心概念

Selector,Channel,Buffer. 在Java.nio是面相块和buffer编程,buffer本身是一块内存,底层实现上是一个数组,数据的读写都是通过Buffer来实现。数据总是从Channel读取到buffer中,或者从buffer写入到channel中。

基本上,所有的 IO 在NIO 中都从一个Channel 开始。Channel 有点象流。 数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中。这里有个图示从NIO到netty(1) 传统IO和装饰器模式/ NIO简介_第2张图片

Channel和Buffer有好几种类型。下面是JAVA NIO中的一些主要Channel的实现:

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

正如你所看到的,这些通道涵盖了UDP 和 TCP 网络IO,以及文件IO。

与这些类一起的有一些有趣的接口,但为简单起见,我尽量在概述中不提到它们。本教程其它章节与它们相关的地方我会进行解释。

以下是Java NIO里关键的Buffer实现:

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

这些Buffer覆盖了你能通过IO发送的基本数据类型:byte, short, int, long, float, double 和 char。

Java NIO 还有个 MappedByteBuffer,用于表示内存映射文件

 

Selector允许单线程处理多个 Channel。如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。例如,在一个聊天服务器中。

这是在一个单线程中使用一个Selector处理3个Channel的图示:

从NIO到netty(1) 传统IO和装饰器模式/ NIO简介_第3张图片

Java NIO可以让你非阻塞的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。

要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。

Java NIO还底层还是使用了linux的零拷贝技术,进一步增强性能,关于零拷贝,会有一篇文章专门涉及。

本节结束

你可能感兴趣的:(java,框架)