Java中高手加QQ群498238384 备注:Java中高手- 呢称 如果对您有帮助,麻烦在右边点个赞哦~~ 什么是IO、NIO、AIO?...Java 1.7引入的NIO 2.0中用到的。...讲一讲Channel 一个Channel(通道)代表和某一实体的连接,这个实体可以是文件、网络套接字等。既可以读又可以写。而流是单向的。...比如,当所有通道都没有数据到达时,也就没有Read事件发生,我们的线程会在select()方法处被挂起,从而让出了CPU资源。...、CharBuffer、IntBuffer等,区别就是读写缓冲区时的单位长度不一样(以对应类型的变量为单位进行读写)。
一般在shell中操作,进程获取信号进行处理,一共有64种信号,在shell中输入 kill -l 可查阅 7.套接字(socket) 套接字(有的时候被译为插座)也是一种进程间通信机制,与其他通信机制不同的是...相对于共享内存可以多对多的读取与写入,套接字只能一对一。此外由于序列化等操作占用大量资源,相对于共享内存,套接字更适合传输少量数据。...套接字:可用于不同机器之间的进程间通信。 线程间的通信方式 锁(Lock) 锁机制包括互斥锁、条件变量、读写锁。 互斥锁提供了以排他方式防止数据结构被并发修改的方法。...能够让协程在事件未发生之前挂起,等待事件发生后被调度并处理,从而有效让出CPU时间。 能够在消息中附带相应的数据。...而进入阻塞可以看成是一个主动的行为(eg.进程I/O时,进程在等待I/O设备完成时,进程主动进入阻塞状态,I/O完成,进程被激活) 挂起态可以分为下面两种: 阻塞挂起状态:进程在外存(磁盘)并等待某个事件的出现
所以上面虽然有个while死循环,但在getReadyIOFd被阻塞了,getReadyIOFd底层也是个系统调用(具体实现我们后面会讲到),在没有可读写的套接字时线程并不会占用CPU。...IO多路复用的实现模型大家多少听过一些,我们先比较下常见的select和epoll select select简单理解就是拿一个数组保存连接套接字,调用select时,会将整个数组拷贝到内核空间中,如果当前数组中没有可读写的套接字...新获取到一个套接字后,将该套接字添加到wq中,等到套接字可读写时,操作系统会将该套接字从wq转到rdlist,然后线程直接处理rdlist中的套接字即可,不需要再遍历全部监听的套接字了。...所以我们需要在第一次读时通过循环read的方式把套接字中的数据全读出来。...在前面,我们使用epoll实现了一个线程管理多个套接字,当某个套接字有读写事件时,epoll_wait调用返回,告诉我们哪些套接字能读,但并不会告诉我们某个套接字上有多少数据可读。
⽹络读写事件注册到事件引擎中; • 当套接字满⾜可读或可写条件时,事件引擎设置套接字对应的事件状态并返回给调⽤者; • 调⽤者根据套接字的事件状态分别『回调』对应的处理过程; ...,操作系统负责将多个线程任务唤⼊唤出; 上下⽂切换: 当操作系统需要将某个线程挂起时,会将该线程在 CPU 寄存器中的栈指针、状态字等保存⾄该线程的内存栈中;当操作系统需要唤醒某个被挂起的线程时...: 每⼀个⽹络连接绑定⼀个套接字句柄,该套接字绑定⼀个协程; 当对⽹络套接字进⾏读或写发生阻塞时,将该套接字添加⾄ IO 调度协程的事件引擎中并设置读写事件,然后将该协程挂起;这样所有处于读写等待状态的...⽹络协程都被挂起,且与之关联的⽹络套接字均由 IO 调度协程的事件引擎统⼀监控管理; 当某些⽹络套接字满⾜可读或可写条件时,IO 调度协程的事件引擎返回这些套接字的状态,IO 调度协程找到与这些套接字绑定的协程对象...⾏合并处理,主要是因为 libfiber 的调度过程是单线程模式的,如果想要在多线程调度器中合并中间态的事件操作则要难很多:在多线程调度过程中,当套接字所绑定的协程因IO 可读被唤醒时,假设不取消该套接字的读事件
; • 当套接字满⾜可读或可写条件时,事件引擎设置套接字对应的事件状态并返回给调⽤者; • 调⽤者根据套接字的事件状态分别『回调』对应的处理过程; • 对于⼤部分基于 TCP 的⽹络应⽤,数据的读写往往不是...,操作系统负责将多个线程任务唤⼊唤出; 上下⽂切换: 当操作系统需要将某个线程挂起时,会将该线程在 CPU 寄存器中的栈指针、状态字等保存⾄该线程的内存栈中;当操作系统需要唤醒某个被挂起的线程时(重新放置在...在网络协程库中,内部有一个缺省的IO调度协程,其负责处理与网络IO相关的协程调度过程,故称之为IO调度协程: 每⼀个⽹络连接绑定⼀个套接字句柄,该套接字绑定⼀个协程; 当对⽹络套接字进⾏读或写发生阻塞时...,将该套接字添加⾄ IO 调度协程的事件引擎中并设置读写事件,然后将该协程挂起;这样所有处于读写等待状态的⽹络协程都被挂起,且与之关联的⽹络套接字均由 IO 调度协程的事件引擎统⼀监控管理; 当某些⽹络套接字满...⾜可读或可写条件时,IO 调度协程的事件引擎返回这些套接字的状态,IO 调度协程找到与这些套接字绑定的协程对象,然后将这些协程追加至协程调度队列中,使其依次运⾏; IO 事件协程内部本身是由系统事件引擎
首先来看下可读事件与可写事件: 当如下任一情况发生时,会产生套接字的可读事件: 该套接字的接收缓冲区中的数据字节数大于等于套接字接收缓冲区低水位标记的大小; 该套接字的读半部关闭(也就是收到了FIN),...对这样的套接字的读操作将返回0(也就是返回EOF); 该套接字是一个监听套接字且已完成的连接数不为0; 该套接字有错误待处理,对这样的套接字的读操作将返回-1。...当如下任一情况发生时,会产生套接字的可写事件: 该套接字的发送缓冲区中的可用空间字节数大于等于套接字发送缓冲区低水位标记的大小; 该套接字的写半部关闭,继续写会产生SIGPIPE信号; 非阻塞模式下,connect...返回之后,该套接字连接成功或失败; 该套接字有错误待处理,对这样的套接字的写操作将返回-1。...因为在实际情况中,我们往往不止一种事件处理器,因此这里将事件处理器接口和实现分开,与C++、Java这些高级语言中的多态类似。
在AF_INET下,以元组(host,port)的形式表示地址。 sk.listen(backlog) 开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。 ...sk.connect_ex(address) 同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061 sk.close() 关闭套接字 sk.recv(bufsize...其中data是包含接收数据的字符串,address是发送数据的套接字地址。 sk.send(string[,flag]) 将string中的数据发送到连接的套接字。...sk.sendall(string[,flag]) 将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 ...一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s ) sk.getpeername() 返回连接套接字的远程地址。
《脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?》...(本文) 4、Socket读写的简单过程理解 当客户端和服务器使用TCP协议进行通信时,客户端封装一个请求对象req,将请求对象req序列化成字节数组,然后通过套接字socket将字节数组发送到服务器,...在互联网技术服务行业工作多年的经验告诉我,如果你对底层机制不了解,你就会不明白为什么对套接字socket的读写会出现各种奇奇乖乖的问题,为什么有时会阻塞,有时又不阻塞,有时候还报错,为什么会有粘包半包问题...我们平时用到的套接字其实只是一个引用(一个对象ID),这个套接字对象实际上是放在操作系统内核中。...当我们对客户端的socket写入字节数组时(序列化后的请求消息对象req),是将字节数组拷贝到内核区套接字对象的write buffer中,内核网络模块会有单独的线程负责不停地将write buffer
Redis 单线程为什么还能这么快? 因为它所有的数据都在内存中,所有的运算都是内存级别的运算。...非阻塞 IO 在套接字对象上提供了一个选项 Non_Blocking,当这个选项打开时,读写方 法不会阻塞,而是能读多少读多少,能写多少写多少。...能读多少取决于内核为套接字分配的读缓冲区内部的数据字节数,能写多少取决于内核为套接字分配的写缓冲区的空闲空间字节数。读方法和写方法都会通过返回值来告知程序实际读写了多少字节。...每个客户端套接字 socket 都有对应的读写文件描述符。...Redis 的定时任务会记录在一个称为最小堆的数据结构中。这个堆中,最快要执行的任 务排在堆的最上方。在每个循环周期,Redis 都会将最小堆里面已经到点的任务立即进行处理。
Java 的 volatile关键字对可见性的保证 Java 的 volatile关键字在保证可见性之前的所做的事情 为什么volatile关键字有时候也不是足够的 什么时候volatile足够了...volatile关键字对效率的影响 Java关键字用于将一个变量标记为“存储在内存中的变量”。...实际上,从java5开始,volatile关键字就不仅仅是保证volatile变量从主存读写,笔者会在后面详细讨论这个问题。...counter = 0; } ** 将一个变量声明为volatile就可以保证写操作,其他线程对这个变量的可见性 ** Java 的 volatile关键字在保证可见性之前的所做的事情 从java5...volatile关键字对效率的影响 读写一个volatile变量的时候,会导致变量直接在主存中读写,显然,直接从主存中读写速度要比从cache中来得慢。
这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据 ——《深入理解Java虚拟机》 我们可用 NIO 中的缓冲区(Buffer)来使用直接内存,不幸的是直接内存只支持...零拷贝 为什么使用直接内存就能如此提高读写性能?因为使用了零拷贝技术。...CPU将数据从套接字缓冲区拷贝到网卡缓冲区 CPU完成拷贝,write()返回从内核态切换回用户态 综上: 读过程有2次状态切换、2次CPU拷贝 写过程有2次状态切换、2次CPU拷贝 在传统模式下,CPU...2.6.3 sendFile + DMA收集 sendFile将内核空间缓冲区中数据的描述信息拷贝到套接字缓冲区中 DMA控制器根据套接字缓冲区的描述信息,将数据从内核缓冲区直接拷贝到网卡 可以减少一次...在Netty这样高性能网络通信框架中,也是经常读写的,所以其底层也涉及到了零拷贝技术 缺点: 读过程中要将数据拷贝到用户缓冲区我们才能进行修改的,而缺失这一环(直接拷贝到套接字缓冲区或网卡)那么我们就不能对数据进行修改
初始化同步器的最大限制值,然后每接受一个套接字就将计数器变量+1,每关闭一个套接字,将计数器变量-1,如此一来,一旦技术变量值>最大限制值,则AQS机制将接受线程阻塞,而停止对套接字的接受。...直到某些套接字处理完,关闭后重新唤起接受线程往下接受套接字。...主要任务有3个任务:处理套接字并响应客户端,连接数计数器减1,关闭套接字。...▶ maxProcessors与minProcessors:在 Java中线程是程序运行时的路径,是在一个程序中与其它控制线程无关的、能够独立运行的代码段。它们共享相同的地址空间。...♧ 依赖注入(DI):Spring 使用 Java Bean对象的Set方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程就是依赖注入的基本思想。
SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。...在AF_INET下,以元组(host,port)的形式表示地址。 sk.listen(backlog) 开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。...其中data是包含接收数据的字符串,address是发送数据的套接字地址。 sk.send(string[,flag]) 将string中的数据发送到连接的套接字。...sk.sendall(string[,flag]) 将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。...bufsize值为1024,最多只能接受1024个字节,那么如果client端发送的数据包特别大时,超过了指定的bufsize的值,超过的不分会留在内核缓冲区中,下次调用recv的时候会继续读剩余的字节
这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据 ——《深入理解Java虚拟机》 我们可用 NIO 中的缓冲区(Buffer)来使用直接内存,不幸的是直接内存只支持...零拷贝 为什么使用直接内存就能如此提高读写性能?因为使用了零拷贝技术。...CPU将数据从套接字缓冲区拷贝到网卡缓冲区 CPU完成拷贝,write()返回从内核态切换回用户态 综上: 读过程有2次状态切换、2次CPU拷贝 写过程有2次状态切换、2次CPU拷贝 在传统模式下,CPU...(总计两次状态切换,2次DMA拷贝,1次CPU拷贝) image.png 2.6.3 sendFile + DMA收集 sendFile将内核空间缓冲区中数据的描述信息拷贝到套接字缓冲区中 DMA控制器根据套接字缓冲区的描述信息...在Netty这样高性能网络通信框架中,也是经常读写的,所以其底层也涉及到了零拷贝技术 缺点: 读过程中要将数据拷贝到用户缓冲区我们才能进行修改的,而缺失这一环(直接拷贝到套接字缓冲区或网卡)那么我们就不能对数据进行修改
,当数据就绪后在读写的时候必须阻塞(区别就绪与读写二个阶段,同步的读写必须阻塞),异步则指主动请求数据后便可以继续处理其它任务,随后等待I/O,操作完毕的通知,这可以使进程在数据读写时也不阻塞。...在套接应用程序中,当调用recv()函数时,未必用户空间就已经存在数据,那么此时recv()函数就会处于等待状态。 ...阻塞模式套接字的不足表现为,在大量建立好的套接字线程之间进行通信时比较困难。...当使用socket()函数和WSASocket()函数创建套接字时,默认都是阻塞的。在创建套接字之后,通过调用ioctlsocket()函数,将该套接字设置为非阻塞模式。...当调用该函数时,套接字会自动地设置为非阻塞方式。 由于使用非阻塞套接字在调用函数时,会经常返回WSAEWOULDBLOCK错误。所以在任何时候,都应仔细检查返回代码并作好对“失败”的准备。
在套接应用程序中,当调用recv()函数时,未必用户空间就已经存在数据,那么此时recv()函数就会处于等待状态。...阻塞模式套接字的不足表现为,在大量建立好的套接字线程之间进行通信时比较困难。...在返回时,该函数返回一个错误代码。图所示,一个非阻塞模式套接字多次调用recv()函数的过程。前三次调用recv()函数时,内核数据还没有准备好。...当使用socket()函数和WSASocket()函数创建套接字时,默认都是阻塞的。在创建套接字之后,通过调用ioctlsocket()函数,将该套接字设置为非阻塞模式。...当调用该函数时,套接字会自动地设置为非阻塞方式。 由于使用非阻塞套接字在调用函数时,会经常返回WSAEWOULDBLOCK错误。所以在任何时候,都应仔细检查返回代码并作好对“失败”的准备。
,这可以使进程在数据读写时也不阻塞。...在套接应用程序中,当调用recv()函数时,未必用户空间就已经存在数据,那么此时recv()函数就会处于等待状态。...阻塞模式套接字的不足表现为,在大量建立好的套接字线程之间进行通信时比较困难。...当使用socket()函数和WSASocket()函数创建套接字时,默认都是阻塞的。在创建套接字之后,通过调用ioctlsocket()函数,将该套接字设置为非阻塞模式。...当调用该函数时,套接字会自动地设置为非阻塞方式。 由于使用非阻塞套接字在调用函数时,会经常返回WSAEWOULDBLOCK错误。所以在任何时候,都应仔细检查返回代码并作好对“失败”的准备。
服务端套接字创建过程 第一步:调用socket函数创建套接字 //成功时返回文件表述符,失败时返回-1 int socket(int __domain, int __type, int __protocol...(Type):是指套接字的传输方式 面向连接的套接字(SOCK_STREAM) 传输过程中数据不会消失 按序传输数据 传输的数据不存在数据边界(Boundary):调用了三次write传递了100字节,...客户端的IP地址和端口号在调用connect函数时由内核自动分配,无需调用标记的bind函数进行分配。 ?...当然,此时服务器端在调用accept函数时进入了阻塞状态,直到客户端调用connect函数为止。 TCP套接字中的I/O缓冲 ?...I/O缓冲在每个TCP套接字中单独存在; I/O缓冲在创建套接字时自动生成; 即使关闭套接字也会继续传递输出缓冲中遗留的数据; 关闭套接字将丢失输入缓冲中的数据; 编写 echosrv.c #include
socket模型中,不同操作调用后会返回不同的套接字类型;socket()方法会返回主动套接字,然后调用listen() 方法,将主动套接字转化为监听套接字,此时可以监听来自客户端的连接请求。...最后调用accept()方法接收到达的客户端连接,并返回已连接套接字; 针对监听套接字,可以设置非阻塞模式:当 Redis 调用 accept() 但一直未有连接请求到达时,Redis线程可以返回处理其他操作...但是要注意的是,调用 accept()时,已经存在监听套接字了; 虽然 Redis线程可以不用继续等待,但是总得有机制继续在监听套接字上等待后续连接请求,并在有请求时通知 Redis;类似的也可以针对已连接套接字设置非阻塞模式...流,就是我们经常听到的select/epoll机制;简单来说在Redis只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字;内核会一直监听这些套接字上的连接请求或数据请求。...epoll 监控的事件中已经发送的事件; epoll也需要调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait
既然有了字节流,为什么还要有字符流? 问题本质想问:不管是文件读写还是网络发送接收,信息的最小存储单元都是字节,那为什么 I/O 流操作要分为字节流操作和字符流操作呢?...在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的 IO 模型。...对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO 操作本身是同步的。 阻塞式I/O模型:默认情况下,所有套接字都是阻塞的。怎么理解?...对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所有等待分组到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用程序缓冲区。...非阻塞式I/O:以下这句话很重要:进程把一个套接字设置成非阻塞是在通知内核,当所请求的I/O操作非得把本进程投入睡眠才能完成时,不要把进程投入睡眠,而是返回一个错误。
领取专属 10元无门槛券
手把手带您无忧上云