精华内容
下载资源
问答
  • 5)三种输入方式:一般数字输入,复用输入、模拟输入。 1)一般数字输入:TTL斯密特触发器作用,由于从引脚输入的高低电平信号不是很完美,所以需要经过斯密特触发器的修整,使信号稳定。 输入寄存器的作用:输入的...

    查看电路原理图
    GPIO内部引脚结构图。
    在这里插入图片描述
    1)内部上下拉电阻:决定默认引脚状态,VDD3.3V Vss–0VGND
    2)默认引脚状态:上拉、下拉、浮空:不舍设置上下拉电压值由引脚所接的“外部外设”决定。
    3)具体设置什么应该引脚接的是什么。
    4)整个引脚的结构分为上下两部,输入/输出。

    5)三种输入方式:一般数字输入,复用输入、模拟输入。
    1)一般数字输入:TTL斯密特触发器作用,由于从引脚输入的高低电平信号不是很完美,所以需要经过斯密特触发器的修整,使信号稳定。
    输入寄存器的作用:输入的数字信号(数据)将缓存在“输入数据寄存器”中,然后程序即可以从“输入数据寄存器”中读出输入的数据,拿到数据后,程序就可以根据需要来使用这个数据了。
    2)复用功能:不经过“数据寄存器”,经TTL修整后,可以交给复用该引脚的其它“片内外设”的寄存器,之后接自己的要求使用。
    使用复用输入,配置GPIO的寄存器外,还要配置USB、DMA、UART这些外设的寄存器,让这些片内外设工作后,才能接收“复用输入”的数据。
    3)模拟输入:无须修整,输入到芯片内部后,交给处理模拟信号的“片内外设”,交给AD,AD就后进行模拟/数字的转换,将模拟信号变为数字信号,什么时候使用。
    比如,温度传感器将温度转为模拟电信号后,需要通过模拟输入由芯片内部的AD,再将其转为数字信号。

    4)三种输出:一般数字输出、复用输出、模拟输出。
    1)一般数字输出:先写入复位/置位寄存器,再将数据导入“输出数据寄存器”然后输出。
    下面还有一种,直接将数据写入“数据输出寄存器”,再输出。
    每组GPIO16个引脚,共用相同的“输入数据寄存器“,”输出数据寄存器“”复位/置位寄存器”等。不过每组GPIO寄存器都是独立的。
    

    “输出控制用于选择输出类型,数字信号可以有两种输出模式,推挽式和开漏式。推挽式输出,两个MOS管都工作,开漏输出只有一个N-MOS管工作,腿玩输出有更加强劲的输出能力,特殊要求时,才会选开漏输出。
    2)复用输出:例:使用LCD相关复用,此时程序会先将图像数据交给"LCD片内外设”,然后通过复用输出路径将输出从引脚输出,交给LCD夜晶以供显示。
    3)模拟输出:例:芯片内部DA将数字信号转换为模拟信号。

    展开全文
  • Java IO 方式有很多种,基于不同的 IO 抽象模型和交互方式,可以进行简单区分。 同步阻塞 IO 首先,传统的 Java.io 包基于流模型实现,提供了我们最熟知的一些 IO 功能,比如 File 抽象,输入输出流等,交互方式是...

    Java 提供了哪些 IO 方式, NIO 如何实现多路复用?

    Java IO 方式

    Java IO 方式有很多种,基于不同的 IO 抽象模型和交互方式,可以进行简单区分。

    同步阻塞 IO

    首先,传统的 Java.io 包基于流模型实现,提供了我们最熟知的一些 IO 功能,比如 File 抽象,输入输出流等,交互方式是同步 、阻塞的方式,也就是说,在读取输入流或者写入输出流是,在读写动作完成之前,线程会一直阻塞在哪,他们之间的调用时可靠的先行顺序。

    java.io 包的好处就是代码比较简单直观,缺点就是 IO 效率和扩展性存在的局限性,容易成为应用性能的瓶颈。

    很多时候,人们也把 java.net下面提供的部分网络API,比如 Socket、 Serversocket、 HttpURLConnection也归类到同步阻塞IO类库,因为网络通信IO行为。

    同步非阻塞IO

    在Java1.4中引入了NIO框架(java.nio包),提供了 Channel、 Selector、 Buffer等新的抽象,可以构建多路复用的、同步非阻塞IO程序,同时提供了更接近操作系统底层的高性能数据操作方

    异步非阻塞IO

    第三,在Java7中,NIO有了进一步的改进,也就是NIO2,引入了异步非阻塞IO方式,也有很多人叫它AIO( Asynchronous IO)。异步IO操作基于事件和回调机制,可以简单理解为,应用操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作。

    什么是同步异步?

    区分同步或异步( synchronous/ asynchronous)。简单来说,同步是一种可靠的有序运行机制,当我们进行同步操作时,后续的任务是等待当前调用返回,才会进行下而异步则相反,其他任务不需要等待当前调用返回,通常依靠事件、回调等机制来实现任务间次序关系

    什么是阻塞非阻塞?

    区分阻塞与非阻塞( blocking/on- blocking)。在进行阻塞操作时,当前线程会处于阻塞状态,无法从事其他任务,只有当条件就绪才能继续,比如 Serversocket新连接建立完毕,或数据读取、写入操作完成;而非阻塞则是不管IO操作是否结束,直接返回,相应操作在后台继续处理。

    • https://docs.oracle.com/javase/tutorial/essential/io/streams.html

    java.io 具体实现

    • IO不仅仅是对文件的操作,网络编程中,比如 Socket 通信,都是典型的IO操作目标。

    • 输入流、输出流( Inputstream/outputstream)是用于读取或写入字节的,例如操作图片文件。

    • Reader/ Writer则是用于操作字符,增加了字符编解码等功能,适用于类似从文件中读取或者写入文本信息。本质上计算机操作的都是字节,不管是网络通信还是文件读取, Reader/ Writer相当于构建了应用逻辑和原始数据之间的桥梁

    • BufferedOutputStream 等带缓冲区的实现,可以避免频繁的磁盘读写,进而提高IO处理效率。这种设计利用了缓冲区,将批量数据进行一次操作,很多IO工具类都实现了Closeable接口,因为需要进行资源的释放。比如,打开 FileInputstream,它就会获取相应的文件描述符( FileDescriptor)

    • 利用 try-with-resources、try-finally 等机制保证 FileInputstream被明确关闭,进而相应文件描述符也会失效,否则将导致资源无法被释放。之前提到的 Cleaner或finalizer 机制作为资源释放的最后保障,也是必要的。

    • https://mp.weixin.qq.com/s?__biz=MzU4NDEwMzU3Mg==&mid=2247484409&idx=1&sn=3493be8a596b09ce0303cde0c0bc9fed&chksm=fd9fa002cae82914d77792d2232a74a76cb41525a164abd3bb1ac012d78edf089e242d3f9d5d&token=2120176138&lang=zh_CN#rd

    image

    Java NIO

    组成部分

    • Buffer , 高效的数据容器,处理布尔类型,所有的原始数据类型,都有相应的Buffer 实现。
    • Channel ,类似 在linux 之类操作系统上看到的文件描述符,是 NIO 中被用来支撑批量式 IO 操作的一种抽象。
      File 或者 Socket ,通常被认为是 比较高层次的抽象,而 Channel 则是更加操作系统底层的一种抽象,这也使得 NIO 可以充分利用现代操作系统底层机制,获得特定场景的性能优化。
    • Selector 是 NIO 实现多路复用的基础,它提供了一种高效的机制,可以检测到注册在Selector 上的多个 Channel 中,是否有 Channel 处于就绪状态,进而实现单线程对多 Channel 的高效处理。
    • Charset 提供了 Unicode 字符串定义,NIO 提供了相应的解码器等,
    Charset.defaultCharset().encode("Hello world!")
    

    Selector 同样是基于底层操作系统机制,不同模式,不同版本都存在区别,例如。在 linux 上依赖 epoll, windows 上 NIO2 依赖的是 iocp。

    • hg.openjdk.java.net/jdk/jdk/file/d8327f838b88/src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java
    • http://hg.openjdk.java.net/jdk/jdk/file/d8327f838b88/src/java.base/windows/classes/sun/nio/ch/Iocp.java

    NIO 能解决什么问题

    通过一个典型场景,为什么需要多路复用,如果需要实现一个服务器应用,只简单要求能同时服务多个客户端请求即可。

    同步阻塞 API 实现

    • 服务器端启动 ServerSocket ,端口0表示自动绑定一个空隙端口。
    • 调用 accept 方法,阻塞等待客户端连接
    • 利用 Socket 模拟一个简单的客户端只进行连接,读取打印。
    • 当连接建立后,启动一个单独线程回复端请求。

    同步阻塞IO 实现

    public class DemoServer extends Thread {
        private ServerSocket serverSocket;
    
        public int getPort() {
            return serverSocket.getLocalPort();
        }
    
        public void run() {
            try {
                serverSocket = new ServerSocket(0);
                while (true) {
                    // 非常占用内存资源,每个客户端启用一个线程是十分不合理
                    Socket socket = serverSocket.accept();
                    RequesHandler requesHandler = new RequesHandler(socket);
                    requesHandler.start();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (serverSocket != null) {
                    try {
                        serverSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    ;
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            DemoServer server = new DemoServer();
            server.start();
            try (Socket client = new Socket(InetAddress.getLocalHost(), server.getPort())) {
                BufferedReader buferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
                buferedReader.lines().forEach(s -> System.out.println(s));
            }
        }
    }
    
    // 简化实现,不做读取,直接发送字符串
    class RequesHandler extends Thread {
        private Socket socket;
    
        RequesHandler(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
            try (PrintWriter out = new PrintWriter(socket.getOutputStream());) {
                out.println("Hello world!");
                out.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    每次 new 一个线程或者销毁一个线程是有明显的开销的,每个线程都有单独的线程结构,非常占用内存资源,每个客户端启用一个线程是十分不合理的, 因此可以采用线程池的方式进行优化.

    伪异步 IO

    也是阻塞IO,采用线程池的方式处理请求,当来一个新的客户端连接时,将请求 Socket 封装成一个 task ,放到线程池中取执行。

    serverSocket = new ServerSocket(0);
    executor = Executors.newFixedThreadPool(8);
    while (true) {
        Socket socket = serverSocket.accept();
        RequesHandler requesHandler = new RequesHandler(socket);
        executor.execute(requesHandler);
    }
    

    通过一个固定大小的线程池,来负责管理工作线程,避免频繁创建,销毁线程的开销。

    image

    试想,如果连接数并不是特别多,只有几百个连接,这种模式可以很好的工作。但是如果连接数急剧上升,这种实现就无法很好的工作,因为线程上下文切换开销会在高并发时变得很明显。

    如果连接数并不是非常多,只有最多几百个连接的普通应用,这种模式往往可以工作的很好。但是,如果连接数量急剧上升,这种实现方式就无法很好地工作了,因为线程上下文切换开销会在高并发时变得很明显,这是同步阻塞方式的低扩展性劣势。

    NIO 实现

    NIO(非阻塞IO) 多路复用机制

    public class NIOServer extends Thread {
        public void run() {
            try (Selector selector = Selector.open(); ServerSocketChannel serverSocket = ServerSocketChannel.open();) {// 创建Selector和Channel
                serverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8888));
                serverSocket.configureBlocking(false);
                // 注册到Selector,并说明关注点
                serverSocket.register(selector, SelectionKey.OP_ACCEPT);
                while (true) {
                    selector.select();// 阻塞等待就绪的Channel,这是关键点之一
                    Set<SelectionKey> selectedKeys = selector.selectedKeys();
                    Iterator<SelectionKey> iter = selectedKeys.iterator();
                    while (iter.hasNext()) {
                        SelectionKey key = iter.next();
                        // 生产系统中一般会额外进行就绪状态检查
                        sayHelloWorld((ServerSocketChannel) key.channel());
                        iter.remove();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private void sayHelloWorld(ServerSocketChannel server) throws IOException {
            try (SocketChannel client = server.accept();) {
                ByteBuffer readBuffer = ByteBuffer.allocate(32);
                client.read(readBuffer);
                System.out.println("Server received : " + new String(readBuffer.array()));
                ByteBuffer writeBuffer = ByteBuffer.allocate(128);
                writeBuffer.put("hello xiaoming".getBytes());
                writeBuffer.flip();
                client.write(writeBuffer);
                //client.write(Charset.defaultCharset().encode("Hello world!"));
            }
        }
    
        public static void main(String[] args) throws IOException {
            NIOServer server = new NIOServer();
            server.start();
            
            try {
                SocketChannel socketChannel = SocketChannel.open();
                socketChannel.connect(new InetSocketAddress(InetAddress.getLocalHost(), 8888));
    
                ByteBuffer writeBuffer = ByteBuffer.allocate(32);
                ByteBuffer readBuffer = ByteBuffer.allocate(32);
    
                writeBuffer.put("hello".getBytes());
                writeBuffer.flip();
    
                while (true) {
                    writeBuffer.rewind();
                    socketChannel.write(writeBuffer);
    //                readBuffer.clear();
                    socketChannel.read(readBuffer);
                    System.out.println("Client received : " + new String(readBuffer.array()));
                }
            } catch (IOException e) {
            }
            
        }
    
    /**
     * @return
     */
    private int getPort() {
        return 8888;
    }
    
    

    image
    这样做的好处:

    • 首先,通过 Selector.open()创建一个 Selector 类似调度员的角色。
    • 然后,创建一个 ServerSocketChannel ,并且向 Selector 注册,并且通过指定 SelectionKey.OP_ACCEPT ,告诉调度员,他关注的是最新连接请求。
    • Selector 阻塞在 select 操作,当有Channel 发送接入请求,就会被唤醒。
    • 在 sayHelloWorld 方法中,通过 socketChannel 和 Buffer 进行数据操作。

    在前面两个样例,阻塞IO和伪异步IO,一个是使用 new 线程的方式,一个是采用线程池管理的方式, IO都是同步阻塞模式,所以需要多线程以实现多任务处理。而 NIO 则是利用了单线程轮询事件的机制,通过高效地定位就绪的Channel,来决定做什么,仅仅select阶段是阻塞的,可以有效避免大量客户端连接时,频繁线程切换带来的问题,应用的扩展能力有了非常大的提高。

    AIO 实现

    JDK 1.7 升级了NIO 类库,升级后的 NIO 也被称为 NIO 2.0 ,NIO 2.0 引入了异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。

    • 通过 java.util.concurrent.Future 类来标识异步操作的结果
    • 在执行异步操作的时候出入一个 java.nio.channels

    跟 NIO 比对

    • 基本抽象很相似, AsynchronousServerSocketChannel对应于NIO例子中的ServerSocketChannel; AsynchronousSocketChannel则对应SocketChannel。
    • 业务逻辑的关键在于,通过指定CompletionHandler回调接口,在accept/read/write等关键节点,通过事件机制调用,这是非常不同的一种编程思路。
    AsynchronousServerSocketChannel serverSock = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress("127.0.0.1", 8888));
    serverSock.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
        final ByteBuffer buffer = ByteBuffer.allocate(1024);
        @Override
        public void completed(final AsynchronousSocketChannel result, Object attachment) {
            buffer.clear();
            try {
                // 把socket中的数据读取到buffer中
                result.read(buffer).get();
                buffer.flip();
                System.out.println("Echo " + new String(buffer.array()).trim() + " to " + result);
                // 把收到的直接返回给客户端
                result.write(buffer);
                buffer.flip();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } finally {
    
            }
        }
    
        @Override
        public void failed(Throwable throwable, Object attachment) {
        }
    });
    

    程序员开发者社区

    展开全文
  • 复用方式

    2016-11-30 00:13:00
    听一个朋友说冷不丁被问了一个问题:类复用方式有哪些? 其实这个问题也算是比较简单,类复用的方式主要有两种:组合和继承。 所谓组合,就是把一个类的实例作为另一个类的属性保存。 所谓继承,就是一个类是另...

    听一个朋友说冷不丁被问了一个问题:类复用的方式有哪些?

    其实这个问题也算是比较简单,类复用的方式主要有两种:组合和继承。

     

    所谓组合,就是把一个类的实例作为另一个类的属性保存。

    所谓继承,就是一个类是另一个类的子类。

    转载于:https://my.oschina.net/xinguimeng/blog/796481

    展开全文
  • title : 每日深耕,勤练不缀之java提供了哪些IO方式?NIO如何实现多路复用? 可以构建高扩展性应用的能力 JAVA IO 很多种,基于不同的IO抽象模型和交互方式 可以进行简单区分 1.传统的java.io包(BIO),基于流模型...

    title : 每日深耕,勤练不缀之java提供了哪些IO方式?NIO如何实现多路复用?

    可以构建高扩展性应用的能力
    JAVA IO 有很多种,基于不同的IO抽象模型和交互方式
    可以进行简单区分
    1.传统的java.io包(BIO),基于流模型实现,提供了我们最熟知的一些IO性能,如:File抽象,输入输出流等
    交互方式是同步,堵塞的方式,在读取输入流或者写入输出流时,在读、写动作完成之前,线程会一直阻塞在那里,它们之间的调用是可靠的线性顺序
    java.io包的好处是代码比较简单,直观,缺点是IO效率和扩展性存在局限,成为性能瓶颈。
    java.net下面提供的部分网络API,比如Socket、ServerSocket、HttpURLConnection也归类到同步阻塞IO类库。
    2.java1.4引入了NIO框架(java.io包),提供了Channel,Selector,Buffer等新的抽象,可以构建多路复用的、同步非阻塞IO程序,,提供了更接近操作系统底层的高性能数据操作方式
    3.java7中,NIO有了进一步的改进,也就是NIO2,引入了异步非阻塞IO方式,也有很多人叫它AIO(Asynchronous IO)。异步IO操作基于事件和回调机制,可以理解为,应用操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作

    在面试中,考察的点涉及方方面面

    • 基础API功能和设计,InputStream/OutputStream和Reader/writer的关系和区别(BIO)
    • NIO AIO的基本组成
    • 给定场景,分别用不同模型实现,分析BIO、NIO等模式的设计和实现原理
    • NIO提供的高性能数据操作方式是基于什么原理,如何使用?
    • 或者,从开发者的角度来看,你觉得NIO自身实现存在哪些问题?有什么改进的想法吗?

    区分同步和异步?
    同步是一种可靠的有序运行机制,当我们进行同步操作时,后续的任务是等待当前调用返回,才会进行下一步,而异步则相反,其他任务不需要等待当前调用返回,通常依靠事件、回调等机制来实现任务间次序关系

    区分阻塞和非阻塞?
    在进行阻塞操作时,当前线程会处于阻塞状态,无法从事其他任务,只有当前条件就绪才能继续。比如:ServerSocket新连接建立完毕,或数据读取,写入操作完成,而 非阻塞 则是不管IO操作是否结束,直接返回,相应操作则在后台处理。

    我们不能说同步和阻塞就是低效,分情况而定。

    对于java.io的总结:

    • IO不仅仅是对文件的操作,网络编程中,比如Socket通信,都是典型的IO 操作目标
    • 输入流,输出流是用于读取或写入字节的,操作图片文件
    • Reader/Writer则是用于操作字符,增加了字符编解码等功能,适用于类似从文件中读取或者写入文本信息。本质上计算机操作的都是字节,不管是网络通信还是文件读取,相当于构建了应用逻辑和原始数据之间的桥梁
    • BufferdOutputStream等缓冲区的实现,可以避免频繁的磁盘读写,进而提高IO处理效率,这种设计利用了缓冲区,将批量数据进行一次操作,使用中不能忘了flush
    • 很多IO工具类都实现了Closeable接口,因为需要进行资源的释放。比如:打开FilelnputStream,它就会获取相应的文件描述符(FileDescriptor),需要try-with-resources、try-finally等机制保证FilelnputStream被明确关闭,进而相应文件描述也会失效,否则将导致资源无法被释放

    JAVA NIO

    NIO的组成部分:
    1.Buffer,高效的数据容器,除了布尔类型,所有原始数据类型都有相应的Buffer实现
    2.Channel,文件描述符,是NIO中被用来支持批量式IO操作的一种抽象。file 、Socket ,被认为是比较高层次的抽象,而 channel则是更加操作系统底层的一种抽象。我们可以通过Socket获取Channel。
    4.Selector,是NIO实现多复用的基础,他提供了一种高效的机制,可以检测到注册在Selector的多个Channel中,是否有Channel处于就绪状态,进而实现单线程对多CHANNNEL的高效管理

    NIO解决的问题
    为什么需要NIO,为什么需要多路复用?
    场景:我们需要实现一个服务器应用,简单要求能够同时服务多个客户端请求

    package DemoClient;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class DemoServer  extends Thread{
        private ServerSocket serverSocket;
        public int getPort(){
            return serverSocket.getLocalPort();//相当于一个平常的成员变量
        }
    
        public void run(){
            try{
                serverSocket =new ServerSocket(0);//服务器端启动ServerSocket,端口0表示自动绑定一个空闲端口
                while (true){
                    Socket socket =serverSocket.accept();//客户端的请求,阻塞等待客户端连接
                    RequestHandler requestHandler =new  RequestHandler(socket) ;
                    requestHandler.start();
                }
            }catch (IOException e){
                e.printStackTrace();
            } finally {
                if(serverSocket !=null){
                    try{
                        serverSocket.close();
                    }catch(IOException e){
                        e.printStackTrace();
                    }
                }
            }
        }
        public static void main(String[] args) throws  IOException{
            DemoServer server =new DemoServer();
            server.start();//服务器开启
            /**
             * 利用Scoket模拟一个简单的客户端,只进行连接、读取、打印
             */
            try(Socket client =new Socket(InetAddress.getLocalHost(),server.getPort())){
                BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(client.getInputStream()));
                bufferedReader.lines().forEach(s -> System.out.println(s));
            }
        }
        
        
        class RequestHandler extends  Thread {
            private Socket socket;
    
            RequestHandler(Socket socket) {
                this.socket = socket;
            }
    
            @Override
            public void run() {//重载
                try (PrintWriter out = new PrintWriter(socket.getOutputStream());) {
                    out.println("hello world");
                    out.flush();
    
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
    
    

    线程实现比较重量级,启动和销毁一个线程有明显开销,每个线程都有单独的线程栈结构 ,占用非常明显的内存,所以,每一个Client启动一个线程都有点浪费

    所以,我们可以修正问题,引入线程池机制来避免浪费

    通过一个固定大小的线程池,来负责管理工作线程,避免频繁创建、销毁线程的开销,这是构建并发服务的典型方式

    在这里插入图片描述

    如果只有几百个连接的普通应用,这种模式往往可以工作很好。但是如果数量急剧上升,这种实现方式就无法很好工作,因为线程上下文切换开销会在高并发时变得很明显,这是同步阻塞方式的低扩展性劣势

    NIO引用的多路复用机制,提供了另外一种思路

    package DemoServerClient;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.nio.charset.Charset;
    import java.util.Iterator;
    import java.util.Set;
    
    public class NIOServer  extends Thread{
        /**NIO的组成1.Buffer   2.channel 多线程并发抽象概念  3.Selector筛选器
         * 同步非阻塞IO框架
         */
        public void run(){
            try(Selector selector =Selector.open();//通过Selector.open()创建一个Selector,作为一个类似调度员的角色
                /**通过创建一个ServerSocketChannnel,并且向Selector注册,通过指定SelectionKey.OP_ACCEPT,
                 * 告诉调度员,它关注的是新的连接请求
                 * 为什么我们要明确配置非阻塞模式呢?因为在阻塞模式下,注册操作是不允许的
                 */
                ServerSocketChannel serverSocket =ServerSocketChannel.open();){//创建channel selector
                serverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(),8888));//创建连接端口,监听
                serverSocket.configureBlocking(false);
                //注册到Selector,并说明关注点
                serverSocket.register(selector, SelectionKey.OP_ACCEPT);
                while(true){
                    /**Selector阻塞在select操作,当有Channel发生接入请求后,就会被唤醒
                     */
                    selector.select();//阻塞等待就绪的Channel,这是关键点之一
                    Set <SelectionKey> selectionKeys =selector.selectedKeys();//建一个selector的HashSet
                    Iterator <SelectionKey> iter =selectionKeys.iterator();//迭代器迭代 selectionKey的Set
                    while(iter.hasNext()){
                        SelectionKey key =iter.next();
                        //生产系统中一般会额外进行就绪状态检查
                        sayHelloWorld((ServerSocketChannel)key.channel());//强制类型转换,找出那个channel
                    }
    
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        /**
         *在此方法中,通过ScoketChannel和Buffer进行数据操作,发送一段字符串
         * @param server
         * @throws IOException
         */
        private void sayHelloWorld(ServerSocketChannel server) throws IOException{
            try(SocketChannel client =server.accept();){//客户端只管发送请求就ok
                client.write(Charset.defaultCharset().encode("helloworld!"));
            }
        }
    
    }
    
    

    IO是同步阻塞模式,需要多线程实现多任务处理
    NIO利用单线程轮询时间的机制,高效定位就绪的Channel,来决定做什么,仅仅select阶段是阻塞的,可以避免大量客户连接时,频繁切换线程带来的问题

    在这里插入图片描述
    异步非阻塞AIO
    java7引入NIO2(AIO)时,又增添了一种额外的异步IO模式,利用事件和回调,处理Accept,Read等操作
    AsychronousServerSocketChannel对应于上面例子的SeverSocketChannel;
    AsychronousSocketChannel对应于SocketChannel
    业务逻辑的关键点在于,通过指定的CompletionHandler回调接口,在accept/read/write等关键节点,通过事件机制调用,实现异步

    展开全文
  • Java IO 方式有很多种,基于不同的 IO 抽象模型和交互方式,可以进行简单区分。首先,传统的 java.io 包,它基于流模型实现,提供了我们最熟知的一些 IO 功能,比如 File 抽象、输入输出流等。交互方式是同步、阻塞...
  • Java IO方式有很多种,基于不同的IO抽象模型和交互方式,可以进行简单区分。 首先,传统的java.io包,它基于流模型实现,提供了我们最熟知的一些IO功能,比如File抽象、输入输出流等。交互方式是同步、阻塞的方式,...
  • IO 一直是软件开发中的核心部分之一,伴随着海量数据增长和分布式系统的发展,IO 扩展能力愈发重要。幸运的是,Java 平台 IO 机制经过不断完善...Java IO 方式有很多种,基于不同的 IO 抽象模型和交互方式,可以进行...
  • Java核心技术面试精讲 - 第11讲 | Java提供了哪些IO方式? NIO如何实现多路复用? I。一直是软件开发中的核心部分之一,伴随着海量数据增长和分布式系统的发展,I。扩展能力愈发重要。幸运的是,Java平台I。机制经过...
  •   IO 一直是软件开发中的核心部分之一,伴随着海量数据增长和分布式系统的发展,IO 扩展能力愈发重要。幸运的是,Java 平台 IO 机制经过不断完善,虽然在...今天我要问你的问题是,Java 提供了哪些 IO 方式? NIO ...
  • 1、引言 在之前的博文中,我们陆续的介绍了I/O复用的三种技术——...这三种方式都是通过某种结构体变量来告诉内核监听哪些文件描述符及其事件。具体的区别如下: select的参数类型是fd_set的文件描述符集合。因为
  • 实现多态的两种方式 一、什么是多态? 父类类型的变量指向子类创建的对象,使用该变量调用父类中一个被子类重写的方法,则父类中的方法呈现出不同的行为特征,这就是多态。 简单的来说编译时方法行为表现的是...
  • 实现多态的两种方式 一、什么是多态? 父类类型的变量指向子类创建的对象,使用该变量调用父类中一个被子类重写的方法,则父类中的方法呈现出不同的行为特征,这就是多态。 简单的来说编译时方法行为表现的是...
  • service两种类型:本地服务(Local Service):用于应用程序内部远程服务(Remote Sercie):用于android系统内部...后者可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已的即可...
  • 在企业级应用开发中,代码的质量是一个重要的指标,复用性好的代码可以提高开发效率减少不必要的麻烦,也是一种很好的编程习惯,那么有哪些方式可以提升代码的复用性呢?本文将会简要分享一些开发经验。 1、微服务...
  • HDL代码应该采用与工艺无关的方式编写,好处是用不同ASIC库都能实现同样功能。这点对IP复用意义重大。多计数器法其实不好,因为依赖于器件延时。 时钟相关逻辑 门控时钟、分频器等时钟逻辑以及复位逻辑,应该在最先...
  • 常见CSS知识点有哪些?CSS是前端三要素之一,是Web前端工程师必须要掌握的知识点。为了快速、系统的掌握企业所需的Web前端技术,很多人选择专业的学习,下面就给大家分享CSS常见知识点分享。  CSS:Cascading ...
  • 合成复用原则 Composite Reuse Principle(CRP) ...组合相比继承有哪些优势? 继承主要有三个作用:表示is-a关系,支持多态性,代码复用。这三个作用都可以通过组合、接口、委托三个技术手段来达成 组合合能
  • <div><p>播放TS 流,我想在解复用(demux)时, 选择性的播放某节目应该用哪些接口,也就是过滤器接口࿰...还是另外的内部调用方式</p><p>该提问来源于开源项目:wang-bin/QtAV</p></div>
  • select()和poll() IO多路复用模型select的缺点:单个进程能够监视的文件描述符的数量存在最大限制,通常是1024,当然可以更改数量,但由于select采用轮询的方式扫描文件描述符,文件描述符数...
  • 我们平时所说的1G、2G、3G、4G、5G都是指第X代蜂窝移动通信系统(X表示1,2,3,4,5…),这种系统可以在非相邻的小区内使用相同的无线资源,即频率复用。虽然平时大家平时聊天时这些名词都是信口拈来,不过这些...
  • python测试框架Vantpy框架基于Selenium2+ unittest 搭建的WebUI自动化测试框架使用POM(页面对象模式)设计,使我们写的代码更加简单,后期更加容易维护以及复用性更高支持多种定位方式,包括(xpath/css/ID/text/link_...
  • C语言是面向过程的,而C++,python,java是面向对象的 — 面向过程的编程思想将一个功能分解为...如果要在实现别的功能,即使功能相差极小,也往往要重新编写代码,所以它可复用性比较低,并且难于维护。 例子: 一孩...
  • 多路I/O复用是一个异步阻塞方式,Linux中提供了select、poll和epoll三种阻塞监听的方式,只有一个进程,避免了CPU在多进程和多线程之间的切换。 反应堆就是阻塞监听的事件的集合。 select的反应堆(监听集合)是一...
  • 今天我们来了解一下poll函数,他和select又有哪些不同,哪些相似。很尴尬我找不到合适的配图Poll函数详解在上一篇文章中我们提到select有如下几个缺点:select函数能打开的文件描述符(fd)有限;select采用轮询的遍历...
  • 今天我们来了解一下poll函数,他和select又有哪些不同,哪些相似。很尴尬我找不到合适的配图Poll函数详解在上一篇文章中我们提到select有如下几个缺点:select函数能打开的文件描述符(fd)有限;select采用轮询的遍历...
  • 设计模式一共23种,分为三大类:创建型模式(Creational Patterns),结构型模式(Structural Patterns),行为型模式(Behavioral Patterns)。还有另一类设计模式:J2EE设计模式。1.创建型模式:提供了一种在创建...
  • 解决问题的思维方式

    2020-10-11 11:14:14
    类似的问题有哪些,现有哪些解决方式 3.创新点,难点 我的问题是什么,已有方法已经解决,复用即可; 如果跟现有的问题不同,区别在哪 4.问题解决后的总结 这次解决了一个问题,下次遇到相同的问题,是否可以...
  • 一、CSS应用样式的方式有哪些 CSS样式应用的方式分为三大类: (1)行内样式 (2)内部样式 (3)外部样式  首先来说行内样式,行内样式从字面上不难理解,就是写在一行里面的样式,即写在标签内的样式,所谓...
  • 文末福利哦~1 简单的“自定义”需求总是在不经意间来临,也许是原生控件丑了点,也许是哪些布局复用的多了些,Leader让改改,写个自定义View解决一下,减少一下重复开发工作,这时候该我们迎难而上了,必要的时候...

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 208
精华内容 83
关键字:

复用方式有哪些