Netty
学习io,学习里面的线程通信
Tellme3
任务艰巨在于漫长。
展开
-
4、Lock锁(是一个接口,但是接口类是特殊的类)
这个Locks类下的三个接口:(接口是特殊的类)什么是公平锁(只能顺序执行),什么是非公平锁(允许插队)其中我们的Syn和这里使用的Lock的实现类的ReentrantLock(可重入锁)默认都是非公平锁第三步:如何使用(根据jdk文档:要先给锁加锁,再将我们的业务代码块放入我们try catch中)最后finally去解锁!!其中使用Lock三部曲:new一个想用的锁给锁加锁(后给try里写业务代码)Finally释放锁测试:简化一下(fro循环下只有一句的时候下面的{}可以不要)原创 2022-11-14 17:34:41 · 360 阅读 · 0 评论 -
48、Nio(Io模型(异步(异步和同步)))
异步是没有阻塞的,只要异步非阻塞。!!!场景:(完成一次数据交流)电话是同步的:什么交数据交流,一来一回才叫交流。这里的要确定接电话就是获取结果(完成交流),这里是一个线程。微信聊天是异步的:一个人发消息过来是一个线程,我们不用确定接不接消息。我们再回消息才是完成数据交流(两个线程)!!!!我们这里是看前面的阻塞/非阻塞/多路复用是同步还是异步的。例如阻塞是同步的就是同步阻塞。第一步:同步阻塞(阻塞io是同步的),是自己线程发起read,数据复制后还是给的前面的线程(自己得结果所以是同步的)原创 2022-11-14 17:26:56 · 382 阅读 · 0 评论 -
47、Nio(Io模型(多路复用))
多路复用(最开始就是一个单线程加selector)在select阻塞(等待事件)后,返回的是一堆事件(而不是前面阻塞io一个事件一个事件的返回了),然后就让他再下面循环里全部处理完了。所以他就不用前面的等待连接,等待数据了(select前面是已经等待事件完成了,我们select后只需要马上向下运行即可(不需等待了))。我们在等待事件的时候将所有的等待了。(若是单线程其中,虽然返回的也是一批事件,循环处理,但是其中处理的时候还是一个一个事件处理的,阻塞一个后面也会阻塞,所以我们加多线程去分别处理事件)!!原创 2022-11-14 17:24:20 · 212 阅读 · 0 评论 -
45、Nio/Bio(概念剖析channel vs stream)
Stream不会自动缓冲数据,而channel会利用系统的发送缓冲区和接收缓冲区Stream只支持阻塞api,channel同时支持阻塞,非阻塞,网络channel可以配合selector实现多路复用(记住只有网络channel才能配合selector使用哦)都为全双工。读写都可以同时进行原创 2022-11-13 15:22:38 · 197 阅读 · 0 评论 -
44、Nio(多线程优化(问题解决2))
Nio(多线程优化(问题解决2))原创 2022-11-13 15:21:43 · 136 阅读 · 0 评论 -
42、Nio(多线程优化(问题分析))
问题:我们的客户端发送了数据,但是客户端打印不了我们可读事件的内容(没有进入worker.select事件)Select方法(事件)是在worker0线程里面执行,而我们register方法(注册)是在boss线程里执行的(他们在不同的线程里执行)但是他们都用的相同的selector(都是worker的selector(选择器))。他们会相互影响,这里只要select阻塞了,那么register就必须等待了(比如事件来了,select被唤醒worker0能运行了,然后boss这个线程才能运行)逻辑:这里原创 2022-11-13 15:19:52 · 169 阅读 · 0 评论 -
38、Nio(网络编程小结)
Nio(网络编程小结) 2、非阻塞3、多路复用(selector)仅仅针对网络io。普通文件io是无法多路复用的(要管理channel嘛)4、selector处理accept事件5、selector处理read事件6、selector处理write事件原创 2022-11-13 15:13:55 · 95 阅读 · 0 评论 -
37、Nio(selector(处理可写内容))
Nio(selector(处理可写内容))第一步:我们用if判断代替while(是否还有剩余内容) 第二步:关注可写事件(多个事件,可以用前面的关注+事件。或者|事件) 第三步:将我们未写完的附件(数据)挂到我们key上面attach 第四步:拿到我们未写完的数据再写 第五步:清理操作,写完后我们就清理一下buffer关联在key(内存占用很大的),并且不再关注可写事件 总结:原创 2022-11-13 15:12:10 · 128 阅读 · 0 评论 -
36、Nio(selector(写入过多问题))
Nio(selector(写入过多问题)) 其中服务器端不能一下子发给客户端。因为网络的发送能力是有限的(网络写缓冲区写满了,写不进去就返回0了),但是这样效率很低,若是我们写缓存满的时候,我们去处理别的操作就好咯(比如写缓冲区满了,我们就去读了,别去一直请求写了),若我们写缓冲区空了就触发一个写事件让他去写好了客户端: 测试:原创 2022-11-13 15:10:20 · 108 阅读 · 0 评论 -
Nio(selector(Bytebuffer大小分配))
Nio(selector(Bytebuffer大小分配)) *Bytebuffer不能被多个channel一起使用*若是我们分配一个Bytebuffer为1Mb若是,百万连接那就要1Tb内存。服务器根本不够使了解决思路:原创 2022-11-12 15:37:55 · 177 阅读 · 0 评论 -
34、Nio(selector(处理消息边界问题(附件与扩容)))
Nio(selector(处理消息边界问题(附件与扩容)))第一步:我们确定这个ByteBuffer的具体位置我们分析一下,其中我们不能将我们的buffer放到全局变量中去,因为这样的话就意味着我们的buffer是所有channel通道共用的(我们需要一个buufer被一个channel使用),所以我们这里用到附件(attachment)也就是我们通道注册到selector的第三个参数,这个知识,其中将buffer注册到selector因为channel也注册到我们selector,那么就是一个通道使用一个原创 2022-11-12 15:37:18 · 160 阅读 · 0 评论 -
33、Nio(selector(处理消息边界问题(容量超出)))
Nio(selector(处理消息边界问题(容量超出)))第一步:我们将前面的处理黏包问题的复制过来处理这个buffer(之前我们处理buffer是我呢就将其读到的数据直接复制到buffer里) 客户端的案例:(这里的read是一个阻塞方法,这样我们就不用在前面打断点,然后debug运行了) 第二步:案例变为超出buffer大小 测试:(逻辑是我们服务器端第一次没读完的时候(不是最后的不算完整),会读第二次,这是它就将第二次当做完整信息打印了) 优化思路:(扩容,当发现buffer不够的时候就变为两倍咯)原创 2022-11-12 15:36:15 · 180 阅读 · 0 评论 -
32、Nio(selector(处理消息边界问题(三种方案)))
1、若是传的数据大于buffer,我们可以将buffer扩容处理第一种方案:传的数据小于buffer,固定消息的长度,我们再给服务器也固定长度读取(容易影响带宽)第二种方案:我们根据分隔符拆分消息,我们创建临时buffer大小,去接收消息(有两个问题1、我们要去遍历消息找到分隔符,时间开销大2、若是其消息长度还是大于buffer长度,还是要考虑第三种方案:我们传消息的时候先传我们消息的大小给我们的服务器。第一种方案:传的数据小于buffer,第二种方案:我们根据分隔符拆分消息。若是传的数据大于buffer,原创 2022-11-12 15:34:42 · 415 阅读 · 0 评论 -
31、Nio(selector(消息边界问题(也就是半包黏包问题)))
Nio(selector(消息边界问题(也就是半包黏包问题)))第一步:我们将read事件Bytebuffer(我们是将这个数据读到一个buffer里(后面打印一下buffer里面的内容))的大小设置的很小。并且将buffer的内容通过字符串打印出来Charset.defaultCharset().decode(buffer) 第二步:客户端发送信息(小于buffer内容没问题,超过就会乱码) 第三步:客户端发送超过buffer大小的数据。(消息边界)这里因为我们的汉字是Utf-8会被解析为三个字节(这里原创 2022-11-12 15:32:52 · 129 阅读 · 0 评论 -
30、Nio(select(处理用户端断开(有read事件)))
Nio(select(处理用户端断开(有read事件)))首先我们要有个理解:我们的客户端不管是强制停止,还是正常断开都会触发一个read事件(只是正常断开的read返回的值是-1)第一步:我们强制停止客户端 服务器出现异常(因为我们的客户端已经强制关闭了,我们的客户端想要再去read就会出现io异常) 第二步:处理方式(我们先给他try catch捕获一下异常)ctrl+alt+T快捷键 此时服务器端一直运行,只是服务器没有停止了 因为我们捕获异常后,这个异常还会进入外层的循环,客户端强制停止后还会触原创 2022-11-12 15:31:49 · 767 阅读 · 0 评论 -
29、Nio(seletor为什么要处理完的key要手动清除(remove))
又开始引入下一个循环了,又将我们的sckey复制到集合中。第二步、他向下运行到selector.select()方法阻塞。总结:我们再处理完我们的事件后,我们的key应该删除。第六步、再往下运行这个客户端连接通道channel。第四步、迭代器循环拿出集合的key打印咯。第一步:首先我们是启动我们服务器端嘛。这时我们客户端去启动。第五步、对这个key进行处理。原创 2022-11-12 15:29:47 · 1001 阅读 · 0 评论 -
28、Nio(selector处理read)
Nio(selector处理read)第一步:我们要处理read,这里我们就不是我们之前将的在什么阻塞模式下的要先进行连接(accept)再进行read了。而是我们统一用事件来判断了。所以我们这里只要监听到通道的读事件,那就是read咯 第二步:优化逻辑,(这里我们不能让这个读事件和上面的连接事件在一起了,我们的事件集合里面可能有accept/read事件。我们需要根据不同的事件去做不同的处理。(若是我们是read事件不需要前面的accept了。))分别if判断执行 这里我们来理解下, 测试:客户端进行连接原创 2022-11-12 15:27:02 · 172 阅读 · 0 评论 -
27、Nio(selector(cancel(事件取消)))
Nio(selector(cancel(事件取消)))第一步:当我监听到客户端的连接请求了,但是我们不进行连接(也就是不进行处理)。那么这个服务又陷入了一个非阻塞(线程一直运行) 第二步:剖析select方法(select的逻辑是,若是这个事件已经被处理过了,那么下次就需要新事件了。没有新事件仍然会阻塞(变为阻塞态),但是若是这个事件没有被处理,那么这个select就又会将这这个为处理的selectorkeys这个集合让线程继续处理(进入下面的扫描集合循环))select后这个事件要么处理,要么取消cane原创 2022-11-12 15:24:57 · 240 阅读 · 0 评论 -
26、Nio(Selector(选择器))处理accept)
这一节就是讲的,一个服务器端的serverSocketChannel(用来模拟服务器端)先注册到selector,然后会将其中的ssckey复制到selector的seletorkeys这个集合(其中selector是一个东西,后面的selector.selectorKeys是一个东西)。得到一个selector.selectorKeys的集合(和前面注册到selector的通道(还关注的事件)是两个东西)其中这个是将上面的selector中的复制到这上面来处理,我们先拿到事件集合(是一个set集合)。原创 2022-11-12 15:22:37 · 686 阅读 · 0 评论 -
25、Nio(非阻塞模式调试(多个客户端的连接和数据的读写))
第三步:(我们用一个客户端发一个数据)其中这个循环不知会检查这个是否有连接建立,还会有个小循环接触这个连接里是否有客户端发送数据来。我们要调试的是非阻塞模式下,单线程能不能处理多个客户端连接和数据读写。第一步:(先启动服务器再启动一个客户端)第二步:(启动第二个客户端,第三客户端)原创 2022-11-11 12:38:08 · 205 阅读 · 0 评论 -
24、Nio(非阻塞模式)
Nio(非阻塞模式)第一步:将ServerSocketChannel(服务器)的ssc设置为非阻塞模式(ssc.configurBlocking(false))(影响的是下面的ssc.accept方法(建立连接)(非阻塞,(没有接收到数据)线程继续运行不会由运行态变为阻塞态。(还是运行态)),这里没有接收到数据,返回的是null值) 将下面的先注释掉,再直接运行这个服务器(也就是说没有客户端来建立连接) 第二步:(将socketChannel(用来和客户端建立连接的通道)的sc设置为非阻塞)影响的就是下面的原创 2022-11-11 12:36:21 · 154 阅读 · 0 评论 -
23、阻塞模式调试2(多个客户端)
阻塞模式调试2(多个客户端)第一步:我们还是之前的客户端,只是发送新的数据测试下 测试:内容为空,因为它还是之前的客户端连接,并不是新的客户端连接。所以无法执行下面的方法 第二步:我们启动一个新的客户端 这里no 测试:他这就收到新的客户端连接了56644出现下面的原因是我们前面发送了hi啊,所以他在我新的连接进来的时候开始接着运行下面了,所以就是收到一起连接的数据(为什么是最后打印的是56644这里分析下,我们只是启动了一个新的连接也是到了断点的位置(没有发数据的),所以他执行到下面也是有两个连接但是这个原创 2022-11-11 12:35:15 · 122 阅读 · 0 评论 -
22、阻塞模式调试1(一个客户端)
第二步:如何让这个线程恢复运行呢?(我们让这个他这个客户端去和服务端建立连接。测试:(这里他又在channel.read()方法(阻塞方法),线程停止了。测试(他最后又阻塞到accpet了(没有新的客户端建立连接))第一步:先将服务器跑起来(到这个accept停止)第三步:我们客户端手动向服务器端发送数据。原创 2022-11-11 12:33:58 · 406 阅读 · 0 评论 -
21、Nio阻塞模式
阻塞:阻塞的是什么(阻塞线程)在没有数据可读的时候,线程就必须阻塞等待了(也就是线程停止)(阻塞想一下线程的状态啊有个阻塞状态(注意阻塞是一种状态,而挂起或者睡眠则是一种行为))当这个有数据来的话这个线程就会马上又活过来了非阻塞:(线程不会不会停止),同步,线程也不会停止,只是让线程进行一个排队再加锁代码演示:(nio理解阻塞模式(这里用的是单线程))服务器端:1、创建了服务(ServerSocketChannel)原创 2022-11-11 12:32:02 · 184 阅读 · 0 评论 -
20、Fileswalk(拷贝多级目录)
Fileswalk(拷贝多级目录) 要判断一下拷贝的内容是文件还是目录他,他们的逻辑是不一样的:如果是目录的话就是创建目录(替换前面的路径就可以了(替换就是replace)) 如果是文件我们才是拷贝文件(就是copy就可以了) 测试:原创 2022-11-11 12:29:24 · 142 阅读 · 0 评论 -
19、Files(walkfiletree(删除多目录))
Files(walkfiletree(删除多目录))问题:若是我们要去删除一个目录,但是这个目录不为空那么就无法删除咯思想:我们进去先给他把目录里面的文件给他删除再出目录的时候把目录删除就ok了 解决: 删库跑路咯原创 2022-11-11 12:27:54 · 160 阅读 · 0 评论 -
18、Files(walkfiletree(遍历目录文件))
我们使用的是访问者模式。原创 2022-11-11 12:26:45 · 206 阅读 · 0 评论 -
17、Path&files
Path&filesPath:文件路径 Files:检测文件是否存在 !!!拷贝文件原创 2022-11-11 12:25:23 · 78 阅读 · 0 评论 -
16、Filechannel(传输数据大于2g时)
Filechannel(传输数据大于2g时)原创 2022-11-11 12:23:55 · 165 阅读 · 0 评论 -
15、Filechannel(传输数据(transferto(单次数据最大传输为2g)))
Filechannel(传输数据(transferto(单次数据最大传输为2g))) Transferto(起始位置,文件大小,目标文件)单次数据最大传输为2g这个to.text他会回自己给你创建的 测试:原创 2022-11-10 20:36:46 · 567 阅读 · 0 评论 -
14、文件编程(fileChannel方法简介)
文件编程(fileChannel方法简介)fileChannel只能工作在阻塞模式。(只有后面的socketchannel配合网络编程才能再非阻塞模式)原创 2022-11-10 20:35:19 · 150 阅读 · 0 评论 -
13、ByteBuffer(黏包半包解析)
ByteBuffer(黏包半包解析)第一步:模拟一个网络黏包,半包 第二步:解析 测试:总结:第二步:解析先注意读写模式的切换(读flip(),写用的是compat(clear的话没有读完的话就重新开始了,不行)而且是没有到\n就去给你拼接下一次了)我们去拿到每个字符(用的是get(i)这个好,不会移动我们position位子)原创 2022-11-10 08:21:21 · 256 阅读 · 0 评论 -
12、ByteBuffer(黏包半包分析)
ByteBuffer(黏包半包分析)网络编程很容易出现黏包,半包的黏包(黏包就是我们喜欢发送一个整体)半包(是我们服务器缓存区有大小限制的。就会给他截断了)原创 2022-11-10 08:19:06 · 151 阅读 · 0 评论 -
11、ByteBuffer(分散读集中写)
1、读(分散读)2、写(集中写)1、读(分散读)我们在读取文件的时候就分别读取到多个buffer里面(分散读取)(就比以前的思路我们读到一个buffer里面后面再按单词拆开好多了(以前的有数据的分割和复制))2、写(集中写)我们再将这三个buffer组合成一个整体再一次写入(而不是以前的将这三个buffer写到一个buffer里面再将大的buffer写入文件(又有数据的拷贝了))原创 2022-11-10 08:18:03 · 192 阅读 · 0 评论 -
10、ByteBuffer(方法演示4(ByteBuffer和字符串相互转换))
ByteBuffer(方法演示4(ByteBuffer和字符串相互转换)) 2、Charset(写进buffer后变为了读模式了。Position变为了0) 测试: !!!这里我们的2和3方式可以ByteBuffer直接转为字符串是英文前面的转为bytebuffer后其自动转为了读模式所以可以直接读出去了 所以我们使用1的写入后再准备读出去就要先变为读模式了原创 2022-11-10 08:16:10 · 397 阅读 · 0 评论 -
9、ByteBuffer(方法演示3(buffer4种读取数据方式))
Buffer读取数据方式2、(buffer.rewind(可以重复读(重头开始读,源码就是将positon设为了0)))Buffer读取数据方式4、(get(i)就是读取位置的字符,不会改变position位置)Buffer读取数据方式3、(mark&reset(算是对前面的rewind的增强吧))buffer读取数据方式1、(buffer.get(一位一位的读,不能重复读))原创 2022-11-10 08:14:41 · 1460 阅读 · 0 评论 -
8、ByteBuffer(方法演示2(allocate堆内存和allocateDirect直接内存))
ByteBuffer(方法演示2(allocate堆内存和allocateDirect直接内存))Allocate:java堆内存:读写效率低,收到gc的影响(因为我们的java对象也是存在堆内存的)!!!Gc的影响堆内存:想象一个场景,其中我在对内存中写入了数据,这个时候我们的java虚拟机出现了内存不足,就触发了gc垃圾回收器。这向buffer写入数据的方法(channel的read和buffer的put)Allocate:java堆内存。向buffer分配空间的方法。而直接内存是不受gc影响的。原创 2022-11-10 08:12:59 · 566 阅读 · 0 评论 -
7、ByteBuffer(方法演示1(切换读写模式,读写))
Position:4,limit在10此时准备再来get读(并不是切换到读模式,而是直接读),这个是时候是读不到的,因为此时get是从position处(4)开始读的。后面为0的第四步:切换为写模式(这里是用的compact(将未读的部分向前移))Position在1,limint还是在10(末尾处)第一步:写操作(写入一个a(16进制))Position:4,limit在10。第三步:切换为读模式再get。此时准备再来get读。原创 2022-11-10 08:10:41 · 692 阅读 · 0 评论 -
6、ByteBuffer内部结构
先像buffer写数据(是用的channel通道)将buffer变为读模式(flip())从buffer中读取数据(buffer.get())将buffer变为写模式(clear()或者compact())其中clear是覆盖以前的数据(指针变为开始位置),compact是将指针指到未场景1:写模式(position这个指针进行移动(写一个移动一个))场景5:另一种切换写模式的办法(compact)场景4:读模式变为写模式(clear下)场景2:flip变为切换为读模式。场景三:读取字节(每次get。原创 2022-11-10 08:06:53 · 305 阅读 · 0 评论 -
5、ByteBuffer(基础使用)
第二步:先准备一个文本文件(我们就传输这个东西)4.1、我们将buffer切换到读的模式4.2、看buffer里是否有剩余的未读数据(每次读一个字节,强转为字符打印)这里我们只能打印出我们设置的缓冲区大小的字节(我们使用循环)。所以这里拿到一个标志(这个read方法有一个返回值)如果他是-1就表是为读到末尾了原创 2022-11-09 21:59:57 · 1224 阅读 · 0 评论