首页 > 其他分享 >面试官:说说Netty对象池的实现原理?

面试官:说说Netty对象池的实现原理?

时间:2024-06-04 15:11:48浏览次数:22  
标签:Netty 面试官 对象 线程 User 原理 WeakOrderQueue Stack

Netty 作为一个高性能的网络通讯框架,它内置了很多恰夺天工的设计,目的都是为了将网络通讯的性能做到极致,其中「对象池技术」也是实现这一目标的重要技术。

1.什么是对象池技术?

对象池技术是一种重用对象以减少对象创建和销毁带来的开销的方法。在对象池中,只有第一次访问时会创建对象,并将其维护在内存中,当再次需要使用对象时,会直接从对象池中获取对象,并在使用完毕后归还给对象池,而不是频繁地创建和销毁对象。

使用对象池技术的优点有以下几个:

  1. 提高性能:复用对象可以减少对象的创建和销毁次数,降低系统开销,提高系统性能和吞吐量。
  2. 减少内存碎片:对象池可以避免频繁地创建和销毁对象,减少内存碎片的产生,提高内存利用率。
  3. 避免频繁GC:减少了对象的创建和销毁,可以减少垃圾回收(GC)的频率,降低系统的负担,提高系统的稳定性。

2.对象池基本使用

Netty 对象池技术的核心实现类为 Recycler,Recycler 主要提供了以下 3 个方法:

  1. get():获取一个可重复使用的对象,如果对象池中有空闲对象,则返回其中一个;否则会创建一个新对象。
  2. recycle(T, Handle):回收一个对象,将对象放回对象池中以便下次复用。
  3. newObject(Handle):当对象池中没有可用对象时,此方法会被调用以创建新的对象实例。

接下来我们写一个 Recycler 对象池的使用 Demo,假设我们有一个 User 类,需要实现 User 对象的复用,具体实现代码如下:

public class UserRecyclerDemo {
    private static final Recycler<User> userRecycler = new Recycler<User>() {
        @Override
        protected User newObject(Handle<User> handle) {
            return new User(handle);
        }
    };

    static final class User {
        private String name;
        private Recycler.Handle<User> handle;
        public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public User(Recycler.Handle<User> handle) {
            this.handle = handle;
        }
        public void recycle() {
            handle.recycle(this);
        }
    }

    public static void main(String[] args) {
        User user1 = userRecycler.get(); 	// 1.从对象池获取 User 对象
        user1.setName("zhangsan"); 			// 2.设置 User 对象的属性
        user1.recycle(); 					// 3.回收对象到对象池
        User user2 = userRecycler.get(); 	// 4.从对象池获取对象
        System.out.println(user1 == user2);
        System.out.println(user2.getName());
    }
}

以上程序的执行结果如下:

true

zhangsan

从上述结果可以看出,当第一次调用 userRecycler.get() 时,因为对象池中尚未存在 user 对象,所以创建了 name 为“zhangsan”的对象。但第二次再调用 userRecycler.get() 时,因为对象池中已经存在了 user 对象,所以直接从对象池中取出了 user 对象,所以 user1==user2 时,得到的结果是 true。

3.对象池技术应用

在 Netty 中,使用 Recycler 对象池管理对象的常见类有以下几个:

  1. PooledHeapByteBuf:管理堆内存中的 ByteBuf 对象。
  2. PooledDirectByteBuf:管理堆外内存中的 ByteBuf 对象。
  3. ChannelOutboundBuffer.Entry:Netty 出站缓冲区(ChannelOutboundBuffer)中,每一个待发送的消息都包装在一个 Entry 对象中。

4.实现原理

要搞清楚 Netty 对象池技术的实现原理,就要搞清楚 Netty 对象池的核心组件,以及组件之间的关系。

Netty 对象池技术的实现依靠以下 4 大组件:

  1. Stack(栈):每个线程都关联一个 Stack(使用 FastThreadLocal 进行存储),用于存储和管理该线程回收的对象。Stack 中存储的是 DefaultHandle 对象,这些 DefaultHandle 对象包装了实际要重用的对象。Stack 是与线程绑定的,每个线程从自己的 Stack 中获取对象。
  2. WeakOrderQueue(弱序队列):当某个线程(非主线程)回收对象时,这些对象不会直接放入主线程的 Stack 中,而是放入 WeakOrderQueue 中。WeakOrderQueue 存储的是从其他线程回收的对象,这些对象被包装在 DefaultHandle 中。WeakOrderQueue 与 Stack 关联,但属于非主线程。当主线程的 Stack 为空时,会尝试从 WeakOrderQueue 中获取对象。
  3. Link(链表):WeakOrderQueue 中的存储单元,用于存储回收的对象。Link 中存储的是 DefaultHandle 对象数组,这些数组包含从其他线程回收的对象。
  4. DefaultHandle:对象的包装类,在 Recycler 中缓存的对象都会包装成 DefaultHandle 类。DefaultHandle 中存储了实际要重用的对象,以及与之相关的元数据。

简单来说,这 4 个组件的关系是,(每个)线程为了保证线程安全和高效性操作,所以会把使用的对象放到 Stack 栈中,且每个线程都有自己的 Stack 栈。当线程中的对象不再被使用时(也就是被回收时),并不会将回收对象直接放到 Stack 中(因为当前线程已经不再使用了),此时会将对象存放到 WeakOrderQueue 队列中,因为 WeakOrderQueue 队列相当于“线程共享的区域”,这样其他线程就可以方便的从 WeakOrderQueue 中获取对象进行重用了。而 WeakOrderQueue 中的存储单元是 Link 链表,它存储的是对象池中的包装对象 DefaultHandle,这就是这四大核心组件之间的关系。

5.线程如何获取对象?

在 Netty 中,获取对象池中对象的流程如下:

  1. 判断 Stack:线程首先会尝试从自己的 Stack 中获取对象。如果 Stack 中有对象,则直接弹出(pop)并返回。
  2. Stack 为空:如果 Stack 为空,线程会检查 WeakOrderQueue。如果 WeakOrderQueue 中有对象,则按照一定的规则(如“1/7规则”,每 7 个移动 1 个)将部分对象转移到 Stack 中,然后从 Stack 中弹出并返回。
  3. 创建新对象:如果 Stack 和 WeakOrderQueue 都为空,线程会调用 newObject() 方法创建一个新的对象,并包装成 DefaultHandle 后放入 Stack 中,然后返回该对象。

通过这样的设计,Netty 的 Recycler 对象池技术能够高效地重用对象,减少内存分配和垃圾收集的开销,提升性能。

课后思考

Netty 是如何利用池化技术管理内存的?讲讲它的具体实现?

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

标签:Netty,面试官,对象,线程,User,原理,WeakOrderQueue,Stack
From: https://www.cnblogs.com/vipstone/p/18230794

相关文章

  • 飞睿uwb定位tag防丢器,蓝牙智能防丢器原理,支持苹果IOS的本地防丢查找
    在当今这个快节奏的社会,人们的注意力经常被各种琐事分散,丢三落四的情况时有发生。随着科技的发展,智能防丢器应运而生,成为帮助我们解决这一烦恼的助手。今天,我们就来深入探讨一款备受瞩目的智能防丢产品——飞睿UWB定位Tag防丢器,它不仅结合了新的蓝牙技术,还拥有自己的APP,支持苹......
  • XSS攻击原理及危害,说的太详细了!(值得收藏)
    随着互联网的高速发展,信息安全问题已经成为企业最为关注的焦点之一,在移动互联网时代,web除了传统的XSS、CSRF等安全问题之外,又时常遭遇网络劫持、非法调用HybridAPI等新型安全问题。当然,浏览器自身也在不断在进化和发展,不断引入CSP、Same-SiteCookies等新技术来增强安全......
  • Netty编程模型入门案例
    在Socket编程模型可以看到发送数据和响应数据直接涉及到的是I/O模型,基于TCP/IP的socket编程使用的是流套接字。那什么是I/O模型呢?简单的理解就是用什么样的通道进行数据的发送和接收——这很大程度上决定了程序通信的性能。下面介绍另一种编程模式——Netty框架的入门案......
  • Java 开发面试题精选:Netty 一篇全搞定
    前言在面试Java开发工程师时,技术面试官不仅会考察候选人对Netty理论知识的掌握程度,还会考察其实际应用能力和问题解决技能。在本篇文章精选的关于Netty的面试题目中,从基础到实战再到一些问题的处理分析,都有所覆盖,能较为全面评估出候选人对Netty的理解和应用能力。如果你......
  • 从零手写实现 nginx-03-nginx 基于 Netty 实现
    前言大家好,我是老马。很高兴遇到你。我们希望实现最简单的http服务信息,可以处理静态文件。如果你想知道servlet如何处理的,可以参考我的另一个项目:手写从零实现简易版tomcatminicatnetty相关如果你对netty不是很熟悉,可以读一下Netty权威指南-01-BIO案例Netty......
  • python3 源码阅读-虚拟机运行原理
    原文阅读源码版本python3.8.3参考书籍<<Python源码剖析>>参考书籍<<Python学习手册第4版>>官网文档目录介绍Doc目录主要是官方文档的说明。Include:目录主要包括了Python的运行的头文件。Lib:目录主要包括了用Python实现的标准库。Modules:该目录中包含了所有用C......
  • meltdown 安全漏洞原理是怎么样的?
    Meltdown是2018年初公开的一种严重的计算机安全漏洞,影响了多种处理器,包括英特尔、ARM和某些AMD处理器。其原理基于利用现代CPU的“推测执行”(speculativeexecution)和“缓存时间差异”(cachetiming)来泄露内存数据。以下是Meltdown漏洞的工作原理:基本原理推测执行(SpeculativeE......
  • OSPF协议基本原理:
    OSPF是OpenShortestPathFirst(开放最短路径优先)RIP协议存在的问题:存在最大15跳的限制,不能适用大规模组网的需求周期性发送全部路由信息,占用大量的带宽资源路由收敛速度慢以跳数作为度量值存在路由环路可能性OSPF协议特点:没有路由跳数的限制使用组播更新变化的路由和网......
  • 水文预报新安江模型原理及Matlab代码
    1 蓄满产流模型原理1.1流域蒸散发    流域蒸散发在流域水量平衡中起着重要作用。植物截流、地面填洼水量及张力土壤蓄水量的消退都耗于蒸散发,蒸散发计算成果直接影响模型产流计算成果。    在新安江模型中,流域蒸散发计算按土壤垂向分布的不均匀性将土层分......
  • Netty服务端代码模板
    /***Echoesbackanyreceiveddatafromaclient.*/publicfinalclassEchoServer{staticfinalintPORT=Integer.parseInt(System.getProperty("port","8007"));publicstaticvoidmain(String[]args)throwsException{......