netty源码解析(4.0)-3 Channel的抽象实现

本文深入剖析了Netty中AbstractChannel和AbstractUnsafe的实现,详细介绍了它们之间的关系以及在Channel接口实现中的作用。重点讲解了register、bind、disconnect、close、write和flush等关键操作的实现逻辑,包括事件触发、线程安全和子类扩展点。通过注释和代码分析,帮助读者理解Netty底层工作原理。
摘要由CSDN通过智能技术生成

AbstractChannel和AbstractUnsafe抽象类

io.netty.channel.AbstractChannel

从本章开始,会有大量的篇幅涉及到代码分析。为了能够清晰简洁的地说明代码的结构和功能,我会用代码注释+独立段落的方式加以呈现。 所以,为你能更好地理解代码,请不要忽略代码中黑体字注释。

 

AbstractChannel和AbstractUnsafe之间的关系

AbstractChannel实现了Channel接口,AbstractUnsafe实现了Unsafe。这两个类是抽象类,他们实现了Channel和Unsafe的绝大部分接口。在AbstractChannel的实现中,每个方法都会直接或间接调用Unsafe对应的同名方法。所有的inbound和outbound方法都是通过pipeline间接调用,其他的辅助方法直接使用unsafe实例调用。pipline和unsafe实例在AbstractChannel的构造方法创建:

protected AbstractChannel(Channel parent) {

this.parent = parent;

unsafe = newUnsafe(); //AbstractChannel没有实现这个方法

pipeline = newChannelPipeline(); // newChannelPipline的实现 return new DefaultChannelPipeline(this);

}

直接调用的例子:

@Override

public SocketAddress localAddres) {

SocketAddress localAddress = this.localAddress;

if (localAddress == null) {

try {

//这里直接调用了Unsafe的localAddress()方法

this.localAddress = localAddress = unsafe().localAddress();

} catch (Throwable t) {

// Sometimes fails on a closed socket in Windows.

return null;

}

}

return localAddress;

}

 

间接调用的例子

@Override

public ChannelFuture bind(SocketAddress localAddress) {

return pipeline.bind(localAddress); //通过pipline间接调用Unsafe的bind方法

}

关于pipline是怎样调用Unsafe方法的,会在后面的Pipline相关章节详细分析,这里只需记住。pipeline所有方法调用最终都会(如果没有改变ChannelContextHandler的默认实现)通过使用newUnsafe创建的Unsafe实例调用Unsafe的同名方法(如果有的话)。

netty给出这一对Abstract实现有两个目的:

  • 进一步明确接口的语意。
  • 简化Channel接口的实现。

下面来具体看一下AbstractUnsafe的主要方法实现。

 

 

AbstractUnsafe的重要实现

 

register实现

@Override

public final void register(EventLoop eventLoop, final ChannelPromise promise) {

if (eventLoop == null) {

throw new NullPointerException("eventLoop");

}

if (isRegistered()) { //检查是否已经注册, 避免重复只需注册动作。

promise.setFailure(new IllegalStateException("registered to an event loop already"));

return;

}

if (!isCompatible(eventLoop)) {//检查eventloop是否满足Channel的要求,由子类实现

promise.setFailure(

new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));

return;

}

 

//设置Channel的EventLoop实例

AbstractChannel.this.eventLoop = eventLoop;

 

if (eventLoop.inEventLoop()) { //检查是否在当前线程中,如果是,直接调用

register0(promise);

} else {

//如果不是,把register0包装到runnable中放到eventloop中调用。

try {

eventLoop.execute(new Runnable() {

@Override

public void run() {

register0(promise);

}

});

} catch (Throwable t) {

logger.warn(

"Force-closing a channel whose registration task was not accepted by an event loop: {}",

AbstractChannel.this, t);

closeForcibly();

closeFuture.setClosed();

safeSetFailure(promise, t);

}

}

}

这个方法的实现为我们展示了netty使用I/O线程的一般套路

if(eventLoop.inEventLoop()){

doSomething();

}else{

eventLoop.execute(new Runnable(){

@Override

public void run() {

doSomething();

}

});

}

对于某个需要放到I/O线性中执行的方法,先检查当前线程是不是I/O线程,是就直接执行,不是就把它包装到Ruannable中放到eventLoop中执行。

register的功能总结一句话就是调用register0, 下面看看register0的实现。

private void register0(ChannelPromise promise) {

try {

// check if the channel is still open as it could be closed in the mean time when the register

// call was outside of the eventLoop

//确保promise没有被取消同时Channel没有被关闭才能执行后面的动作

if (!promise.setUncancellable() || !ensureOpen(promise)) {

return;

}

boolean firstRegistration = neverRegistered;

doRegister(); //执行真正的register操作,留改子类实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FastThreadLocal 是 Netty 中的一个优化版 ThreadLocal 实现。与 JDK 自带的 ThreadLocal 相比,FastThreadLocal 在性能上有所提升。 FastThreadLocal 的性能优势主要体现在以下几个方面: 1. 线程安全性:FastThreadLocal 使用了一种高效的方式来保证线程安全,避免了使用锁的开销,使得在高并发场景下性能更好。 2. 内存占用:FastThreadLocal 的内部数据结构更加紧凑,占用的内存更少,减少了对堆内存的占用,提高了内存的利用效率。 3. 访问速度:FastThreadLocal 在访问时,使用了直接索引的方式,避免了哈希表查找的开销,使得访问速度更快。 在 Netty 源码中,FastThreadLocal 主要被用于优化线程的局部变量存储,提高线程之间的数据隔离性和访问效率。通过使用 FastThreadLocal,Netty 在高性能的网络通信中能够更好地管理线程的局部变量,提供更高的性能和并发能力。 引用中提到的代码片段展示了 Netty 中的 InternalThreadLocalMap 的获取方式。如果当前线程是 FastThreadLocalThread 类型的线程,那么就直接调用 fastGet 方法来获取 InternalThreadLocalMap 实例;否则,调用 slowGet 方法来获取。 fastGet 方法中,会先尝试获取线程的 threadLocalMap 属性,如果不存在则创建一个新的 InternalThreadLocalMap,并设置为线程的 threadLocalMap 属性。最后返回获取到的 threadLocalMap。 slowGet 方法中,通过调用 UnpaddedInternalThreadLocalMap.slowThreadLocalMap 的 get 方法来获取 InternalThreadLocalMap 实例。如果获取到的实例为 null,则创建一个新的 InternalThreadLocalMap,并将其设置到 slowThreadLocalMap 中。最后返回获取到的 InternalThreadLocalMap。 综上所述,FastThreadLocal 是 Netty 中为了优化线程局部变量存储而设计的一种高性能的 ThreadLocal 实现。它通过减少锁的开销、优化内存占用和加快访问速度来提升性能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [FastThreadLocal源码分析](https://blog.csdn.net/lvlei19911108/article/details/118021402)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Netty 高性能之道 FastThreadLocal 源码分析(快且安全)](https://blog.csdn.net/weixin_33871366/article/details/94653953)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值