IO系列第三篇——NIO(Selector)

Java NIO学习(三)Selector监听事件+NIO服务器实例 书接上文上一篇博客说了一下SelectionKey这个对象的一些常用属性,为这一篇文章的NIO服务器实例算是做了一些铺垫。不过在展示服务端实例代码之前,还要说几点细节上的东西。Selector如何选择就绪的通道//这个方法可能会阻塞,直到至少有一个已注册的事件发生,或者当一个或者更多的事件发生时 selector.select();NIO明明是非阻塞的IO,为何会阻塞这是第一章Java NIO学习( 阅读详情

NIO核心— 选择器Selector

1 概念

Selector 一般称 为选择器 ,当然你也可以翻译为 多路复用器 。它是Java NIO核心组件中的一个,用于检查一个或多个NIO Channel(通道)的状态是否处于可读、可写。如此可以实现单线程管理多个channels,也就是可以管理多个网络链接。
在这里插入图片描述
上一篇进行文件IO时用到的FileChannel并不支持非阻塞操作,NIO主要就是进行网络IO的学习, Java NIO中的网络通道是非阻塞IO的实现,基于事件驱动,非常适用于服务器需要维持大量连接但数据交换量不大的情况,例如一些即时通信的服务等等。

在之前的BIO中我们已经编写过Socket服务器:
1、ServerSocket–BIO模式的服务器,一个客户端一个线程,虽然写起来简单,但是如果连接越多,线程就会越多,容易耗尽服务器资源而使其宕机。
2、使用线程池优化–让每个客户端的连接请求交给固定数量线程的连接池处理,写起来简单还能处理大量连接。但是线程的开销依然不低,如果请求过多,会出现排队现象。
如果使用java中的NIO,就可以用非堵塞的IO模式处理,这种模式下可以使用一个线程,处理大量的客户端连接请求。
只有在连接真正有读写事件发生时,才会进行读写,就大大地减少了系统开销,并且不必为每个连接都创建一个线程, 不用去维护多个线程。避免了多线程之间的上下文切换导致的开销。

2 选择器(Selector)

Selector:选择器类管理着一个被注册的通道集合的信息和它们的就绪状态。通道是和选择器一起被注册的,并且使用选择器来更新通道的就绪状态。
Selector是一个抽象类,实际使用的时候用的是SelectorImpl。
在这里插入图片描述
在这里插入图片描述

2.1 Selector类的select的三种不同形式:

1、无参的select():
Selector类的select()方法会无限阻塞等待,直到有信道准备好了IO操作,或另一个线程唤醒了它(调用了该选择器的wakeup())返回SelectionKey
2、带有超时参数的select(long time):
当需要限制线程等待通道就绪的时间时使用,如果在指定的超时时间(以毫秒计算)内没有通道就绪时,它将返回0。将超时参数设为0表示将无限期等待,那么它就等价于select( )方法了。
3、selectNow()是完全非阻塞的:
该方法执行就绪检查过程,但不阻塞。如果当前没有通道就绪,它将立即返回0

通过调用Selector.open()方法创建一个Selector对象,如下:

Selector selector = Selector.open();

2.2 概念

SelectionKey:一个SelectionKey键表示了一个特定的通道对象和一个特定的选择器对象之间的注册关系。这种注册的关系共有四种:
在这里插入图片描述
常用方法:
在这里插入图片描述

2.3 SelectableChannel介绍

2.3.1 类关系

在这里插入图片描述

2.3.2 两个重要方法

1、configureBlocking()方法:设置阻塞或非阻塞模式

public abstract SelectableChannel configureBlocking(boolean block)

SelectableChannel抽象类的configureBlocking() 方法是由 AbstractSelectableChannel抽象类实现的,SocketChannel、ServerSocketChannel、DatagramChannel都是直接继承了
AbstractSelectableChannel抽象类 (上图明确展示了这些类关系)。

2、register()方法 注册一个选择器并设置监听事件

public abstract SelectionKey register(Selector sel, int ops)

register() 方法的第二个参数是一个interset集合 ,指通过Selector监听Channel时对什么事件感兴趣。
可以监听四种不同类型的事件:
Connect
Accept
Read
Write

通道触发了一个事件意思是该事件已经就绪。比如某个Channel成功连接到另一个服务器称为“ 连接就绪 ”。一个ServerSockeChannel准备好接收新进入的连接称为“ 接收就绪 ”。一个有数据可读的通道可以说是“ 读就绪 ”。等待写数据的通道可以说是“ 写就绪 ”。

这四种事件用SelectionKey的四个常量来表示:

SelectionKey.OP_CONNECT
SelectionKey.OP_ACCEPT
SelectionKey.OP_READ
SelectionKey.OP_WRITE

如果你对不止一种事件感兴趣,使用或运算符即可,如下:

int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
2.3.3 ServerSocketChannel

ServerSocketChannel用来在服务器端监听新的客户端Socket连接.
常用的方法除了两个从SelectableChannel类中继承而来的两个方法configureBlocking()和register()方法外,还有以下要记住的方法:
在这里插入图片描述

2.3.4 SocketChannel

SocketChannel,网络IO通道,具体负责读写操作。NIO总是把缓冲区的数据写入通道,或者把通道里的数据读出到缓冲区(buffer) 。
常用方法如下所示:
常用的方法除了两个从SelectableChannel类中继承而来的两个方法configureBlocking()和register()方法外,还有以下要记住的方法:
在这里插入图片描述

3 案例

案例1 NIO服务器端–与客户端练习

服务器端

package NIOTest;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NIOServer {
    public static void main(String[] args) throws IOException {
        //创建一个 服务器
        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();

//      绑定服务器端口
      serverSocketChannel.bind(new InetSocketAddress(10086));
//      (重要)设置为非堵塞模式
        serverSocketChannel.configureBlocking(false);
//        创建selector对象
        Selector selector=Selector.open();
//        将通道注册到selector中, 并监听请求连接时间
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//        循环等待客户端的链接
        while(true){
            if (selector.select(5000)==0){
                System.out.println("服务器:怎么还没有人连接我,我生气了!!!");
                /*
                * 服务器干自己的事情,但是一直在监听客户端的连接
                * */
                continue;
            }
            // 获取Selectionkey 集合
            Set <SelectionKey> selectionKeys=selector.selectedKeys();
            Iterator <SelectionKey> iterator=selectionKeys.iterator();
            while (iterator.hasNext()){
                SelectionKey key=iterator.next();
                if (key.isAcceptable()){
                    //获取连接的客户端  serverSocketChannel负责连接操作
                    SocketChannel socketChannel=serverSocketChannel.accept();
                    //设置为非堵塞
                    socketChannel.configureBlocking(false);
                    System.out.println("客户端进来了新的连接"+socketChannel.hashCode());
                    //注册
                    socketChannel.register(selector,SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                }
                if (key.isReadable()){ //读 --》  客户端发送来的消息  SocketChannel 负责读写操作
                    SocketChannel socketChannel=(SocketChannel) key.channel();
                    ByteBuffer buffer =(ByteBuffer) key.attachment();
                    socketChannel.read(buffer);
                  //  System.out.println(bytes.length); //1024
                  //  String msg=new String(buffer.toString()); //java.nio.HeapByteBuffer[pos=11 lim=1024 cap=1024]
                    buffer.flip();
                    byte [] data =new byte[buffer.limit()];
                    buffer.get(data);
                    System.out.println("客户端发来消息了"+new String(data));
                }
                iterator.remove();
            }
        }
    }
}


当没有客户端连接的时候:每五秒输出一次
在这里插入图片描述
客户端:

package NIOTest;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;

public class NIOClient {
    public static void main(String[] args) throws IOException {
        SocketChannel socketChannel=SocketChannel.open();
        socketChannel.configureBlocking(false);
        InetSocketAddress inetSocketAddress= new InetSocketAddress("127.0.0.1",10086);
        if (!socketChannel.connect(inetSocketAddress)){
            while (!socketChannel.finishConnect()){
                System.out.println("没连接上我继续连接,我先干点其他的事");
            }
        }
        String msg="hi,小李";
        ByteBuffer buffer=ByteBuffer.wrap(msg.getBytes());
        socketChannel.write(buffer);
        System.in.read();
    }
}

在这里插入图片描述

案例2 -聊天室

客户端:

package chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;

public class chatClient {
    private final  String HOSTNAME="127.0.0.1";
    private  final  int PORT =10086;
    private SocketChannel socketChannel;
    private Selector selector;
    private  String userName;

    public chatClient(){
        //初始化
        try {
            socketChannel=SocketChannel.open(new InetSocketAddress(HOSTNAME,PORT));
            socketChannel.configureBlocking(false);
            selector=Selector.open();
            socketChannel.register(selector, SelectionKey.OP_READ);
            userName=socketChannel.getLocalAddress().toString();
            System.out.println(userName+"准备好了!!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public  void sendInfo(String info){
        try {
            info=userName+info;
            socketChannel.write(ByteBuffer.wrap(info.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void readInfo(){
        try {
            int readyChannel =selector.select();
            if (readyChannel>0){
                Iterator <SelectionKey>iterator=selector.selectedKeys().iterator();
                while (iterator.hasNext()){
                    SelectionKey key = iterator.next();
                    if (key.isReadable()){
                        SocketChannel channel=(SocketChannel)key.channel();
                        ByteBuffer buffer=ByteBuffer.allocate(1024);
                        int len=socketChannel.read(buffer);
                        String  msg =new String(buffer.array(),0,len);
                        System.out.println(msg);
                    }
                    iterator.remove();
                }
            }else {
                System.out.println("没有准备就绪的通道");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        chatClient chatClient=new chatClient();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    chatClient.readInfo();
                }
            }
        }).start();
        Scanner scanner=new Scanner(System.in);
        while (scanner.hasNextLine()){
            String msg=scanner.nextLine();
            chatClient.sendInfo(msg);
        }
    }
}

服务端:

package chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class chatServer {
    private ServerSocketChannel serverSocketChannel;
    private Selector selector;
    private static final  int  PORT=10086;

    public chatServer() {
        //完成属性的初始化
        try {
            serverSocketChannel=ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(PORT));
            serverSocketChannel.configureBlocking(false);
            selector=Selector.open();
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //监听事件,监听客户端的连接
    public void listening(){

            try {
                while (true){
                int num=selector.select(5000);
            if (num>0){
                Iterator <SelectionKey>iterator=selector.selectedKeys().iterator();
               while (iterator.hasNext()){
                   SelectionKey key = iterator.next();
                   if (key.isAcceptable()){
                       //连接到服务器的客户端
                       SocketChannel socketChannel=serverSocketChannel.accept();
                       socketChannel.configureBlocking(false);//非堵塞
                       socketChannel.register(selector,SelectionKey.OP_READ);
                       System.out.println("欢迎"+socketChannel.getRemoteAddress()+"连接成功 进入了聊天室内!");
                   }
                   if (key.isReadable()){ //处理客户端的通信请求
                       //处理数据的读取,和转发给除了自己之外的客户端
                     ReadData(key);
                   }
                   //避免 一直处理同一事件
                   iterator.remove();
               }
            }else {
                System.out.println("server一直在等待客户端连接");
            }
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
    }
    //处理数据的读取
    private  void ReadData(SelectionKey key)  {
        SocketChannel socketChannel=null;
        try {
            //拿到了当前的客户端消息
            socketChannel=(SocketChannel) key.channel();
            ByteBuffer buffer=ByteBuffer.allocate(1024);
           int len= socketChannel.read(buffer);
           if (len>0){
               buffer.flip();
               byte [] data =new byte[buffer.limit()];
               buffer.get(data);
               String msg=new String(data);
               System.out.println("客户端发送来了消息"+msg);
               //转发消息给其他客户端
               System.out.println("服务器开始转发消息");
               for (SelectionKey selectionKey : selector.keys()) {
                   SelectableChannel channel = selectionKey.channel();
                     //排除除了自己的其他客户端的连接
                   if (channel instanceof SocketChannel && channel!=socketChannel){
                      SocketChannel client=(SocketChannel) channel;
                      ByteBuffer buffer1=ByteBuffer.wrap(msg.getBytes());
                      client.write(buffer1);
                   }
               }
           }
        } catch (IOException e) {
            try {
                System.out.println(socketChannel.getRemoteAddress()+"离开了聊天室");
                key.cancel();//取消注册
                socketChannel.close();//关闭通道
            } catch (IOException ex) {
                //ex.printStackTrace();
            }

        }
    }

    public static void main(String[] args) {
        chatServer chatServer=new chatServer();
        chatServer.listening();
    }

}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4 BIO VS NIO

BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。

NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。

BIO (Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的I/O 处理模型来应对更高的并发量。

NIO (New I/O): NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解为Nonblocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。 NIO提供了与传统BIO模型中的 Socket 和 ServerSocket 相对应的 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。

大数据-基础NIO-什么是NIO?NIO三大组件Buffer、Channel、Selector的特点 一、NIO简介 1、Java中的IO介绍 BIO:BlockingIO,同步式阻塞式IO,即传统的IO,是Java中最早期的流 NIO:Non-BlockingIO,又称New IO,同步式非阻塞式IO,是JDK1.4提供的流 AIO:AsynchronousIO,异步式非阻塞式IO,可以认为是NIO的二代版本,是JDK1.8提供的流 2、概述 NIO是JDK1.4出现的一个新的用于进行数据传输的流 全称是Non-Blocking IO,是一种同步式非阻塞式的IO,也是一种能供进行多路复用的I 阅读详情

相关推荐

Java中的IO与NIO面试题

1、Java 中 IO 流? Java 中 IO 流分为几种? 按照流的流向分,可以分为输入流和输出流; 按照操作单元划分,可以划分为字节流和字符流; 按照流的角色划分为节点流和处理流。 Java Io 流共涉及 40 多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java I0 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的。 InputStrea...

qwe123147369的博客 1886

NIO-SocketChannel.configureBlocking(false)作用

非阻塞模式 可以设置 SocketChannel 为非阻塞模式(non-blocking mode).设置之后,就可以在异步模式下调用connect(), read() 和write()了。 connect() 如果SocketChannel在非阻塞模式下,此时调用connect(),该方法可能在连接建立之前就返回了。为了确定连接是否建立,可以调用finishConnect()的方法。像这样: socketChannel.configureBlocking(false); socketChanne

luzhensmart的专栏 4634

Java中的IO与NIO篇----第三篇

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。

pleaseprintf的博客 988

NIO(三):源码分析_初始化部分

1,ServerSocketChannel初始化 1.1,ServerSocketChannel serverSocketChannel = ServerSocketChannel.open() ServerSocketChannel.open() public static ServerSocketChannel open() throws IOException { // 先获取...

zp_zhang的博客 490

ENVI5.6 批量处理GF-2/GF-6/GF-7:从安装到融合的完整自动化流程

本文详细介绍了ENVI5.6环境下批量处理GF-2/GF-6/GF-7卫星数据的完整自动化流程,包括环境配置、工具安装、正射校正、图像融合等关键步骤。通过实战案例和优化技巧,帮助用户高效完成高分卫星影像处理,提升工作效率。特别针对GF-6和GF-7的特殊处理要点进行了深入解析。

weixin_42546392的博客 179

合成孔径雷达(SAR)的常见工作模式

随着星载SAR技术研究的深入发展,单一的条带模式已经无法满足当今时代的需求,因此许多新的工作模式相继被提出。这些新模式在分辨率和测绘宽度等方面都有所提高,接下来将简要介绍几种常用的工作模式。

m0_51390495的博客 2314

解决方法:Cannot connect to VM Socket operation on nonsocket: configureBlocking

Cannot connect to VM

idesvo的专栏 3万+

【项目案例】前后端分离项目 【Web图书管理系统 】SpringBoot + Vue + Element UI + Mysql

Web图书管理系统

激流丶的博客 5396

Java NIO | 并发环境下非阻塞IO技术

Java NIO(New IO)是Java平台提供的一种用于高效处理I/O操作的API。它引入了一组新的类和概念,以提供更好的性能和可扩展性。非阻塞模式是Java NIO中的一种I/O模式,它允许程序在等待数据准备好时继续执行其他任务,而不是一直等待数据的到达或操作的完成。

devops 3790

PX4飞控神经网络控制:从仿真到嵌入式部署实战

神经网络控制正逐步革新传统PID在无人机领域的统治地位。通过将深度学习模型部署到PX4飞控硬件,实现了从传感器数据直接生成电机指令的端到端控制。这种架构依赖TensorFlow Lite Micro等轻量级推理框架,在STM32等嵌入式处理器上可达到93μs级推理速度。关键技术突破包括:基于NVIDIA Isaac Gym的高效仿真训练、模型量化压缩技术(如8位整数量化)、以及与PX4原生安全架构的无缝集成。该方案在mRobotics Pixracer Pro等硬件上验证了可行性,为无人机姿态控制、视觉导航

weixin_30570101的博客 403

【BUAA】【计组】计算机组成 pre (含详细解析)

BUAA 计算机组成 本文章旨在为@走肖暂时无法接通的系列文章创造一个目录,收藏本文章,方便查阅! 1. 入门测试 2. 基础知识 3. Logisim   欢迎来到 Logisim 的世界   Logisim 门电路   Logisim 组合电路   Logisim 时序电路   Logisim 仿真与调试   应用与挑战 4. Verilog 与仿真工具   前言   ISE 入门   VCS 入门   Verilog 语法   Verilog 题目实例与分析   Verilog 工程的设计开发调试

Schrodinger007的博客 9809

TCP通信的 BIO(同步阻塞),NIO(同步非阻塞),AIO(异步非阻塞)三种通信方式

Channel(通道) ServerSocketChannel和SocketChannel创建连接 同步阻塞实现 /* 实现同步非阻塞的服务器 相关的类: java.nio.channels.ServerSocketChannel:针对面向流的侦听套接字的可选择通道。 获取对象的方式: static ServerSocketChannel open() 打开服务器套接字通道。 成员方法: ServerSocketChannel

m0_48811221的博客 1004

QT快速配置MSVC2017编译环境(3分钟极简指南)

本文提供了一份3分钟极简指南,帮助开发者快速配置QT的MSVC2017编译环境。通过断网安装、精准勾选组件和配置QT Creator编译器路径等步骤,大幅提升QT开发效率。MSVC2017作为Windows平台高性能C++编译器,特别适合处理大型QT项目,编译速度优势明显。

weixin_30399821的博客 503

IO 与 NIO

阻塞:当一条线程执行或者方法时,这条线程会一直阻塞直到读取到了一些数据或者要写出去的数据已经全部写出,在这期间这条线程不能做任何其他的事情。非阻塞:与原有的有同样的作用和目的,但是使用的方式完全不同,支持面向缓冲区的、基于通道的操作。将以更加高效的方式进行文件读写操作。的核心在于:通道和缓冲区。通道表示打开设备(例如:文件、套接字)的连接。若需要使用系统,需要获取用于连接设备的通道以及用于容纳数据的缓冲区。对数据进行处理。当出现 、等方法是就会阻塞。 三、阻塞 IO解决办法 可以通过线程池创建多线程,为每一

程序猿进阶 1349

四足狗机器人硬件开发技术栈详解

本文系统介绍了四足狗机器人的硬件开发技术,重点分析了五大核心模块:机械结构(骨架设计)、动力系统(关节驱动)、感知系统(环境监测)、控制系统(决策中枢)和电源系统(能源管理)。文章详细阐述了各模块的选型标准、技术要点和协同设计原则,提供了从需求定位到组装调试的完整开发流程,并针对常见问题给出解决方案。随着材料轻量化、模块标准化和AI集成化的发展趋势,四足机器人硬件将向更灵活、更智能的方向演进,为工业巡检、应急救援等场景提供更强大的移动平台支持。

start_up_go的博客 284

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Java IO和NIO

转载请注明链接: Java提供了哪些IO方式? NIO如何实现多路复用? Java IO和NIO 版本号:2018/9/12-1(18:24) Java IO和NIO 基本概念 同步和异步 阻塞和非阻塞 IO/BIO NIO NIO2 问题汇总 参考资料 基本概念 1、Java IO方式有哪些? 传统java.io包:文件...

feather(猎羽) 1万+

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

网络IO之NIO

网络IO之NIO NIO库是在JDK1.4中才引入,弥补了原来的I/O(BIO)的不足,它是一个高速的、面向块的I/O。 NIO有两层含义: 在java层面:nio称为new io,是一套全新的操作io的api。 在OS层面:nio称为no-blocking io,系统调用socket函数可以设置一个NONBLOCK的参数,实现调用方法时不会阻塞线程。 与BIO的主要区别 面向流与面向缓冲 BIO是面向流的,面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能

morris 2万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Java NIO编程实例之三Selector

Java NIO主要包含三个概念,即缓冲区(Buffer)、通道(Channel)和选择器(Selector)。前面的文章已经介绍了缓冲区和通道,本文则讲述最复杂的选择器Selector。 本文是本系列的第三篇文章,关于缓冲区Buffer可以看第一篇: https://zhuanlan.zhihu.com/p/25701512 关于通道Channel可以看第二篇: https://zhuan

LogicTeamLeader的专栏 2594

【Java NIO】— 详解 Selector

在前一篇文章中码哥分析了 ServerSocketChannel 两种模式的缺点阻塞模式:所有阻塞方法都会引起线程的暂停,根本无法应用到业务中来非阻塞模式:CPU 一直在空转,浪费资源所以,如果是我们服务端单独使用 ServerSocketChannel 确实是很麻烦,典型的吃力不讨好。故而我们希望有一个组件能够统一管理我们的 Channel,这个组件就是选择器 Selector。

smart_an的专栏 1194

NIO的总结,NIO与IO的区别,NIO的优势,带你了解NIO

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Ma...

u011770875的博客 2763

NIO与传统IO的区别

 传统的socket IO中,需要为每个连接创建一个线程,当并发的连接数量非常巨大时,线程所占用的栈内存和CPU线程切换的开销将非常巨大。使用NIO,不再需要为每个线程创建单独的线程,可以用一个含有限数量线程的线程池,甚至一个线程来为任意数量的连接服务。由于线程数量小于连接数量,所以每个线程进行IO操作时就不能阻塞,如果阻塞的话,有些连接就得不到处理,NIO提供了这种非阻塞的能力。 小

周宏亮G的日志 5万+

IO和NIO的区别

主要内容 NIO简介 Java NIO 是 java 1.4,之后新出的一套IO接口NIO中的N可以理解为Non-blocking,不单纯是New。 NIO的特性/NIO与IO区别 IO是面向流的,NIO是面向缓冲区的 IO流是阻塞的,NIO流是不阻塞的 IO没有选择器,NIO有选择器 读数据和写数据方式 从通道进行数据读取 :创建一个缓冲区,然后请求通道读取数据。 从通道进行数据写入 :创建一...

Bacchus的博客 3485

NIO之旅Selector

之前的文章介绍了Buffer和Channel,今天这篇文章简单聊一下Selector。 Selector是NIO中最为重要的组件之一,我们常常说的多路复用器就是指的Selector组件。Selector组件用于轮询一个或多个NIO Channel的状态是否处于可读、可写。通过轮询的机制就可以管理多个Channel,也就是说可以管理多个网络连接。 轮询机制 首先,需要将Channel注册到Selector上,这样Selector才知道需要管理哪些Channel 接着Selector会不断轮询其上注册的Ch

程铭程铭你快成名的博客 7706

【NIO】小结:Buffer、Channel、Selector 关系

文件IO: BIO:读/写(人) --> 文件(终点) NIO:读/写(人) --> Buffer(车) ==> Channel(高速路) --> 文件(终点) => TPR模式:一个连接对应一个线程 –> TRP模型的根本原因是线程会出现阻塞 –> 阻塞的原因是不确定性,即该连接要占用该线程多久,那么就会傻傻等待客户端的指令(注:实际的读写时间很短,可以忽略不计) ==> 那可不可以在事件确定的前提下,采用一种单线程的轮询机制 什么事件?四种事件

A minor 1455

Android NIO 系列教程(四) -- Selector

系列文章: Android 网络系列更新计划 Android NIO 系列教程(一) NIO概述 Android NIO 系列教程(二) – Channel Android NIO 系列教程(三) – Buffer 前面几篇文章,我们已经认识了 selector ,它是一个可以检测 一个 或 多个 channel ,并且能够知道该 channel 的读写状态的组件,通过这种方式,一个线程...

夏至的稻穗的博客 1286
上一篇: IO系列第二章——NIO (Buffer&&Channel)
下一篇: Vagrant的安装和使用(附带安装Centos 7教程)
凌晨里的无聊人
博客等级 码龄8年 2320粉丝 206原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌晨里的无聊人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值