bytebuffer

Reactor模型

半世苍凉 提交于 2020-03-25 16:43:13
要无障碍阅读本文,需要对NIO有一个大概的了解,起码要可以写一个NIO的Hello World。 说到NIO、Netty,Reactor模型一定是绕不开的,因为这种模式架构太经典了,但是好多人在学习的时候,往往会忽视基础的学习,一上来就是Netty,各种高大上,但是却没有静下心来好好看看Netty的基石——Reactor模型。本文就带着大家看看Reactor模型,让大家对Reactor模型有个浅显而又感性的认识。 说到Reactor,不得不提到一篇文章,文章作者是大名鼎鼎的Doug Lea,Java中的并发包就是出自他之手,下面我试着从文章中挑出一些重要的内容,结合我的理解,来说说Reactor模型,看看Doug Lea大神的脑回路是多么的与众不同。 经典的服务设计 这是最为传统的Socket服务设计,有多个客户端连接服务端,服务端会开启很多线程,一个线程为一个客户端服务。 在绝大多数场景下,处理一个网络请求有如下几个步骤: read:从socket读取数据。 decode:解码,因为网络上的数据都是以byte的形式进行传输的,要想获取真正的请求,必定需要解码。 compute:计算,也就是业务处理,你想干啥就干啥。 encode:编码,同理,因为网络上的数据都是以byte的形式进行传输的,也就是socket只接收byte,所以必定需要编码。 下面我们来看看传统的BIO代码:

NIO系列:4.NIO快速入门

妖精的绣舞 提交于 2020-03-17 11:48:09
前面的文章介绍了NIO的三大核心组件,现在编写一个 NIO 入门案例,实现服务器端和客户端之间的数据简单通讯(非阻塞): 服务端代码: import java . net . InetSocketAddress ; import java . nio . ByteBuffer ; import java . nio . channels . * ; import java . util . Iterator ; import java . util . Set ; public class NIOServer { public static void main ( String [ ] args ) throws Exception { //创建ServerSocketChannel -> ServerSocket ServerSocketChannel serverSocketChannel = ServerSocketChannel . open ( ) ; //得到一个Selecor对象 Selector selector = Selector . open ( ) ; //绑定一个端口6666, 在服务器端监听 serverSocketChannel . socket ( ) . bind ( new InetSocketAddress ( 6666 ) ) ; /

9种 OOM 常见原因及解决方案

余生长醉 提交于 2020-03-16 21:46:54
当 JVM 内存严重不足时,就会抛出 java.lang.OutOfMemoryError 错误。本文总结了常见的 OOM 原因及其解决方法,如下图所示。如有遗漏或错误,欢迎补充指正。 1、Java heap space 当堆内存(Heap Space)没有足够空间存放新创建的对象时,就会抛出 java.lang.OutOfMemoryError:Javaheap space 错误(根据实际生产经验,可以对程序日志中的 OutOfMemoryError 配置关键字告警,一经发现,立即处理)。 原因分析 Javaheap space 错误产生的常见原因可以分为以下几类: 1、请求创建一个超大对象,通常是一个大数组。 2、超出预期的访问量/数据量,通常是上游系统请求流量飙升,常见于各类促销/秒杀活动,可以结合业务流量指标排查是否有尖状峰值。 3、过度使用终结器(Finalizer),该对象没有立即被 GC。 4、内存泄漏(Memory Leak),大量对象引用没有释放,JVM 无法对其自动回收,常见于使用了 File 等资源没有回收。 解决方案 针对大部分情况,通常只需要通过 -Xmx 参数调高 JVM 堆内存空间即可。如果仍然没有解决,可以参考以下情况做进一步处理: 1、如果是超大对象,可以检查其合理性,比如是否一次性查询了数据库全部结果,而没有做结果数限制。 2、如果是业务峰值压力

NIO socket 的简单连接池

元气小坏坏 提交于 2020-03-16 11:52:13
某厂面试归来,发现自己落伍了!>>> 在最近的项目中,需要写一个socket 与 底层服务器通信的模块。在设计中,请求对象被封装 xxxRequest,消息返回被封装为 xxxResponse. 由于socket的编程开发经验少,一开始我使用了短连接的方式,每个请求建立一个socket通信,由于每个socket只进行一次读写,这大大浪费了 系统资源。 于是考虑使用长连接,系统公用一个client socket 并对send 操作进行加锁,结果在处理并发的时候,各种慢,各种等待。没有办法,考虑使用两节池,预先创建多个 client socket 放入 连接池,需要发送请求时从连接池获取一个socket,完成请求时放入连接池中。下面是一个简单的实现。 private static String IP=GlobalNames.industryIP; private static int PORT =Integer.parseInt(GlobalNames.industryPort); private static int CONNECTION_POOL_SIZE = 10; private static NIOConnectionPool self = null; private Hashtable<Integer, SocketChannel> socketPool = null; /

Java NIO系列教程(八) SocketChannel

纵然是瞬间 提交于 2020-03-16 11:51:54
某厂面试归来,发现自己落伍了!>>> 原文链接 作者: Jakob Jenkov Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。可以通过以下2种方式创建SocketChannel: 打开一个SocketChannel并连接到互联网上的某台服务器。 一个新连接到达ServerSocketChannel时,会创建一个SocketChannel。 打开 SocketChannel 下面是SocketChannel的打开方式: SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80)); 关闭 SocketChannel 当用完SocketChannel之后调用SocketChannel.close()关闭SocketChannel: socketChannel.close(); 从 SocketChannel 读取数据 要从SocketChannel中读取数据,调用一个read()的方法之一。以下是例子: ByteBuffer buf = ByteBuffer.allocate(48); int bytesRead = socketChannel.read(buf);

八, SocketChannel

徘徊边缘 提交于 2020-03-16 11:51:33
某厂面试归来,发现自己落伍了!>>> Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。可以通过以下2种方式创建SocketChannel: 打开一个SocketChannel并连接到互联网上的某台服务器。 一个新连接到达ServerSocketChannel时,会创建一个SocketChannel。 打开 SocketChannel 下面是SocketChannel的打开方式: 1 SocketChannel socketChannel = SocketChannel.open(); 2 socketChannel.connect(newInetSocketAddress(" http://jenkov.com ",80)); 关闭 SocketChannel 当用完SocketChannel之后调用SocketChannel.close()关闭SocketChannel: 1 socketChannel.close(); 从 SocketChannel 读取数据 要从SocketChannel中读取数据,调用一个read()的方法之一。以下是例子: 1 ByteBuffer buf = ByteBuffer.allocate(48); 2 intbytesRead = socketChannel.read(buf); 首先,分配一个Buffer

我所理解的NIO

北慕城南 提交于 2020-03-15 10:39:26
在Java的NIO中,有三个比较重要的概念:Buffer、Channel和Selector。 结合上一篇文章提到的送花的例子。Buffer对应花,Channel对应A和B与花之间的联系,Selector就是不断进行轮询的线程。 Channel 分为ServerSocketChannel和SocketChannel,是客户端与服务端进行通信的通道。 ServerSocketChannel用户服务器端,职责就是监听客户端的连接请求。一旦通过允许,就会建立与该客户端对应的SocketChannel。一个服务端的一个端口只能建立一个ServerSocketChannel用来监听连接。 SocketChannel具有唯一性。一个客户端可能链接多个服务端,那就是多个SocketChannel。服务端与多个客户端建立的连接就有多个SocketChannel。 Selector 是用来负责阻塞轮询的线程,可以通过其静态方法Seletor.open()创建。服务端创建后通过Channel的register方法注册到ServerSocketChannel上,等待客户端连接。客户端同样创建Seletor后通过Channel的register方法注册到SocketChannel上。 当客户端的SocketChannel指定服务端的port和ip进行connect请求之后

增量capacity分配的ByteBuffer实现

旧时模样 提交于 2020-03-12 09:34:45
文章目录 前言 Ozone内部的增量ByteBuffer实现 引用 前言 对于Java nio ByteBuffer,我们常常会拿来做缓冲数据的处理。如果我们就为了图方便,每次数据读写操作专门allocate一个比较大capacity的ByteBuffer,这样会造成不必要的JVM heap的浪费。但是如果我们转而变为多个小ByteBuffer的动态申请,又会加大ByteBuffer的管理协调 操作。那么有什么办法能结合上述二者的特点,做到既不浪费JVM heap空间的使用,又不用在业务上执行复杂的ByteBuffer逻辑。本文笔者介绍一个Ozone内部实现的增量ByteBuffer的实现。增量ByeBuffer在外部使用上和ByteBuffe原生r操作方法语义完全兼容,内部增量allocate capacity操作对调用方而言完全透明。 Ozone内部的增量ByteBuffer实现 这里简单介绍下Ozone的背景,Ozone作为对象存储系统,在存储对象文件的时候,会涉及到大量小数据对象的写入,以Chunk文件的形式进行物理存储。在读写chunk数据的过程中,Ozone使用了ByteBuffer做中间数据的存储。在初始实现中,Ozone内部初始的ByteBuffer allocate的capacity是比较大的,也不管用户写入的数据有多大。为此

java.nio.ByteBuffer 以及flip,clear及rewind区别

假如想象 提交于 2020-03-11 10:26:02
Buffer 类 定义了一个可以线性存放primitive type数据的容器接口。Buffer主要包含了与类型(byte, char…)无关的功能。 值得注意的是 Buffer及其子类都 不是线程安全 的。 每个Buffer都有以下的属性: capacity 这个Buffer最多能放多少数据。capacity一般在buffer被创建的时候指定。 limit 在Buffer上进行的读写操作都不能越过这个下标。当写数据到buffer中时,limit一般和capacity相等,当读数据时, limit代表buffer中有效数据的长度。 position 读/写操作的当前下标。当使用buffer的相对位置进行读/写操作时,读/写会从这个下标进行,并在操作完成后, buffer会更新下标的值。 mark 一个临时存放的位置下标。调用mark()会将mark设为当前的position的值,以后调用reset()会将position属性设 置为mark的值。mark的值总是小于等于position的值,如果将position的值设的比mark小,当前的mark值会被抛弃掉。 这些属性总是满足以下条件: 0 <= mark <= position <= limit <= capacity limit和position的值除了通过limit()和position()函数来设置

Java NIO学习笔记之二-图解ByteBuffer

生来就可爱ヽ(ⅴ<●) 提交于 2020-03-11 10:25:37
ByteBuffer前前后后看过好几次了,实际使用也用了一些,总觉得条理不够清晰。 《程序员的思维修炼》一本书讲过,主动学习,要比单纯看资料效果来的好,所以干脆写个详细点的文章来记录一下。 概述 ByteBuffer是NIO里用得最多的Buffer,它包含两个实现方式: HeapByteBuffer 是基于Java堆的实现,而 DirectByteBuffer 则使用了 unsafe 的API进行了堆外的实现。这里只说HeapByteBuffer。 使用 ByteBuffer最核心的方法是 put(byte) 和 get() 。分别是往ByteBuffer里写一个字节,和读一个字节。 值得注意的是,ByteBuffer的读写模式是分开的,正常的应用场景是:往ByteBuffer里写一些数据,然后flip(),然后再读出来。 这里插两个Channel方面的对象,以便更好的理解Buffer。 ReadableByteChannel 是一个从Channel中读取数据,并保存到ByteBuffer的接口,它包含一个方法: <!-- lang: java --> public int read(ByteBuffer dst) throws IOException; WritableByteChannel 则是从ByteBuffer中读取数据,并输出到Channel的接口: <!-- lang