先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
正文
close = false;
}
} catch (Throwable t) {
handleReadException(pipeline, byteBuf, t, close); //@13
} finally {
// Check if there is a readPending which was not processed yet.
// This could be for two reasons:
// * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(…) method
// * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(…) method
//
// See https://github.com/netty/netty/issues/2254
if (!config.isAutoRead() && !isReadPending()) {
removeReadOp();
}
}
}
代码@1,如果未开启自动读,并且没有读事件等待,则移除读事件。
代码@2,移除读事件,在具体的子类中实现,在AbstractNioUnsafe中的具体实现:
protected final void removeReadOp() {
SelectionKey key = selectionKey();
// Check first if the key is still valid as it may be canceled as part of the deregistration
// from the EventLoop
// See https://github.com/netty/netty/issues/2104
if (!key.isValid()) {
return;
}
int interestOps = key.interestOps();
if ((interestOps & readInterestOp) != 0) {
// only remove readInterestOp if needed
key.interestOps(interestOps & ~readInterestOp);
}
}
代码@3,允许消息预读取最大次数,循环次数,主要是避免一个通道大量数据的读写而拖慢其他通道的处理。
代码@4,内存分配的方式,这里的目的就是可以分配足够的内存字节以便于从通道读取数据。下文会重点讲解。
代码@5,利用代码@4处的分配器,分配一个ByteBuf,用于接收通道中的数据。
代码@6,从通道中读取数据,具体在子类中实现,在NioSocketChannel中的实现如下:
@Override
protected int doReadBytes(ByteBuf byteBuf) throws Exception {
return byteBuf.writeBytes(javaChannel(), byteBuf.writableBytes());//javaChannel()方法返回的就是java.nio.SocketChannel
}
这里涉及到ByteBuf与通道打交道,最终还是会落到java.nio.Channel和java.nio.ByteBuffer上去,所以下文我也觉得有必要深究一下整个API的调用,增强对java.nio原生api的使用。
代码@7,如果没有读到可用数据,则回收刚申请的ByteBuf,如果读到的数据小于0,则说明需要将通道关闭。设置close=true,并跳出循环。
代码@8,将读到的内容(ByteBuf)通过管道传播到各个Handler,此时Handler的处理,默认都会在IO线程中处理。
代码@9,如果本次读到的字节数小于分配ByteBuf的可写字节数,说明该通道已经没有数据可读,结束本次循环。
代码@10,再次从通道中读取,直到读取次数已经超过配置的最大预读取次数,maxMessagesPreRead,如果是ServerChannel或AbstractNioChannel,则默认为16,其他的默认为1。
代码@11,触发读完成事件。
代码@12,该方法非常重要,IO线程将本次读取的字节数反馈给 接收ByteBuf分配器,方便下一次分配合理的ByteBuf,足够用,但不能超过太多。
代码@13,如果发生异常触发异常事件。
对整个通道读事件处理,上述是主要的处理流程,接下来重点分析如下两个方面代码@4: RecvByteBufAllocator和代码@8
2.1 RecvByteBuffAllocator系列类分析
/**
-
Allocates a new receive buffer whose capacity is probably large enough to read all inbound data and small enough
-
not to waste its space.
*/
public interface RecvByteBufAllocator {
/**
-
Creates a new handle. The handle provides the actual operations and keeps the internal information which is
-
required for predicting an optimal buffer capacity.
*/
Handle newHandle();
interface Handle {
/**
-
Creates a new receive buffer whose capacity is probably large enough to read all inbound data and small
-
enough not to waste its space.
*/
ByteBuf allocate(ByteBufAllocator alloc);
/**
-
Similar to {@link #allocate(ByteBufAllocator)} except that it does not allocate anything but just tells the
-
capacity.
*/
int guess();
/**
-
Records the the actual number of read bytes in the previous read operation so that the allocator allocates
-
the buffer with potentially more correct capacity.
-
@param actualReadBytes the actual number of read bytes in the previous read operation
*/
void record(int actualReadBytes);
}
}
该接口主要要解决的问题就是:在处理通道读事件的时候,如何确定需要分配多大的ByteBuf呢?
对如下英文进行通俗化的理解:
- Allocates a new receive buffer whose capacity is probably large enough to read all inbound data and s
mall enough
* not to waste its space.
分配一个接收ByteBuf,希望这个容量足够大,能够容纳通道中可读数据,但又尽量少,够用就好,别浪费空间。
2)guess 方法,只返回猜测,建议的容量(capacity),不执行实际的内存申请。
3)Records the the actual number of read bytes in the previous read operation so that the allocator allocates the buffer with potentially more correct capacity.
记录上传读到的实际字节的大小,以便分配器更加准确的分配正确的容量。
2.1.1 FixedRecvByteBufAllocator 固定容量分配,该方式简单,但忽略了IO线程的反馈。
/**
* The {@link RecvByteBufAllocator} that always yields the same buffer
* size prediction. This predictor ignores the feed back from the I/O thread.
*/
public class FixedRecvByteBufAllocator implements RecvByteBufAllocator
2.1.2 AdaptiveRecvByteBufAllocator 自适应分配算法
1)概述
/**
* The {@link RecvByteBufAllocator} that automatically increases and
* decreases the predicted buffer size on feed back.
*
* It gradually increases the expected number of readable bytes if the previous
* read fully filled the allocated buffer. It gradually decreases the expected
* number of readable bytes if the read operation was not able to fill a certain
* amount of the allocated buffer two times consecutively. Otherwise, it keeps
* returning the same prediction.
*/
AdaptiveRecvByteBufAllocator 根据IO线程的反馈自动增加或减少预期的buffer size。
如果上一次读填满了分配的缓存区,则增大猜测缓存区的大小,如果上一次读没有填满分配的缓冲区,则减少。
2)AdaptiveRecvByteBufAllocator 源码分析
1、核心属性详解
static final int DEFAULT_MINIMUM = 64; // 分配的最小容量
static final int DEFAULT_INITIAL = 1024; // 初始容量
static final int DEFAULT_MAXIMUM = 65536; // 最大容量64k
private static final int INDEX_INCREMENT = 4; //增长索引数,在SIZE_TABLE下的索引
private static final int INDEX_DECREMENT = 1; // 减少索引数
private static final int[] SIZE_TABLE; //小于512个字节,按16个字节递增,大于512字节,成倍增长
// SIZE_TABLE的初始化,其实这里有效使用的最大内存为65536, 64K
static {
List sizeTable = new ArrayList();
for (int i = 16; i < 512; i += 16) { //小于512字节,从16开始,以16递增
sizeTable.add(i);
}
for (int i = 512; i > 0; i <<= 1) { //大于512字节,成倍增长,该循环在超过int最大值时退出
sizeTable.add(i);
}
SIZE_TABLE = new int[sizeTable.size()];
for (int i = 0; i < SIZE_TABLE.length; i ++) {
SIZE_TABLE[i] = sizeTable.get(i);
}
}
private final int minIndex; // DEFAULT_MINIMUM 所在SIZE_TABLE中的下标
private final int maxIndex; // DEFAULT_MAXIMUM 所在SIZE_TABLE中的下标
private final int initial; // 初始时,分配的buffer大小,默认为1K
2、构造方法
/**
-
Creates a new predictor with the default parameters. With the default
-
parameters, the expected buffer size starts from {@code 1024}, does not
-
go down below {@code 64}, and does not go up above {@code 65536}.
*/
private AdaptiveRecvByteBufAllocator() {
this(DEFAULT_MINIMUM, DEFAULT_INITIAL, DEFAULT_MAXIMUM);
}
/**
-
Creates a new predictor with the specified parameters.
-
@param minimum the inclusive lower bound of the expected buffer size
-
@param initial the initial buffer size when no feed back was received
-
@param maximum the inclusive upper bound of the expected buffer size
*/
public AdaptiveRecvByteBufAllocator(int minimum, int initial, int maximum) {
if (minimum <= 0) {
throw new IllegalArgumentException("minimum: " + minimum);
}
if (initial < minimum) {
throw new IllegalArgumentException("initial: " + initial);
}
if (maximum < initial) {
throw new IllegalArgumentException("maximum: " + maximum);
}
int minIndex = getSizeTableIndex(minimum); //@1
if (SIZE_TABLE[minIndex] < minimum) {
this.minIndex = minIndex + 1;
} else {
this.minIndex = minIndex;
}
int maxIndex = getSizeTableIndex(maximum);
if (SIZE_TABLE[maxIndex] > maximum) {
this.maxIndex = maxIndex - 1;
} else {
this.maxIndex = maxIndex;
}
this.initial = initial;
}
构造方法,主要是初始化minIndex、maxIndex,initial。重点看一下getSizeTableIndex方法的详解:
private static int getSizeTableIndex(final int size) {
for (int low = 0, high = SIZE_TABLE.length - 1;😉 { //典型的二分查找算法
if (high < low) { //@1
return low;
}
if (high == low) { //@2
return high;
}
int mid = low + high >>> 1;
int a = SIZE_TABLE[mid];
最后
一次偶然,从朋友那里得到一份“java高分面试指南”,里面涵盖了25个分类的面试题以及详细的解析:JavaOOP、Java集合/泛型、Java中的IO与NIO、Java反射、Java序列化、Java注解、多线程&并发、JVM、Mysql、Redis、Memcached、MongoDB、Spring、Spring Boot、Spring Cloud、RabbitMQ、Dubbo 、MyBatis 、ZooKeeper 、数据结构、算法、Elasticsearch 、Kafka 、微服务、Linux。
这不,马上就要到招聘季了,很多朋友又开始准备“金三银四”的春招啦,那我想这份“java高分面试指南”应该起到不小的作用,所以今天想给大家分享一下。
请注意:关于这份“java高分面试指南”,每一个方向专题(25个)的题目这里几乎都会列举,在不看答案的情况下,大家可以自行测试一下水平 且由于篇幅原因,这边无法展示所有完整的答案解析
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
Boot、Spring Cloud、RabbitMQ、Dubbo 、MyBatis 、ZooKeeper 、数据结构、算法、Elasticsearch 、Kafka 、微服务、Linux。
这不,马上就要到招聘季了,很多朋友又开始准备“金三银四”的春招啦,那我想这份“java高分面试指南”应该起到不小的作用,所以今天想给大家分享一下。
[外链图片转存中…(img-vHyAp998-1713424035290)]
请注意:关于这份“java高分面试指南”,每一个方向专题(25个)的题目这里几乎都会列举,在不看答案的情况下,大家可以自行测试一下水平 且由于篇幅原因,这边无法展示所有完整的答案解析
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-eqL2py8E-1713424035290)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!