2024-04-04  阅读(47)
版权声明:本文为博主付费文章,严禁任何形式的转载和摘抄,维权必究。 本文链接:https://www.skjava.com/mianshi/baodian/detail/7066971601

回答

在 Netty 中,对象池技术是 Netty 的性能优化技术,它是通过重用对象来减少对象创建和销毁的开销,从而提高应用程序的性能和 GC 的频率。

ByteBuf 是 Netty 中数据的载体,Netty 对它采用了对象池技术。ByteBuf 分为池化和非池化两种 ByteBuf。其中池化的ByteBuf可以重用内存空间,从而减少了内存分配和垃圾回收的压力。当请求一个新的ByteBuf时,Netty会首先检查池中是否有可用的 ByteBuf 对象,如果有,则直接返回一个现成的对象;如果没有,则创建一个新对象并在使用后将其返回池中。

Netty的对象池技术主要依赖于Recycler类。Recycler 在 Netty 中是一个轻量级的对象池,借助 Recycler,Netty 可以完成对对象的重复使用。当 Netty 中的一个对象(如ByteBuf)不再使用了,它可以被“回收”到Recycler中,而不是被垃圾回收器回收。当需要一个新对象时,可以从Recycler中获取一个已经存在的实例并重用它,而不是创建一个新的实例。

Recycler 的底层设计有点儿复杂,详细情况阅读下面的【扩展】部分。

扩展

Recycler 快速上手

对象池(英语:Object Pool Pattern)是一种设计模式。一个对象池包含一组已经初始化过且可以使用的对象,可以在有需求时创建和销毁对象。池的使用对象可以从池子中取得对象,对其进行操作处理,并在不需要时归还给池子而非直接销毁它。

Recycler 是 Netty 提供的自定义的轻量级的对象池,借助 Recycler 我们可以完成对 Java 对象的重复使用,下面大明哥就演示如何使用 Recycler。

@NoArgsConstructor
public class User {
    private String name;

    private Integer age;

    private Recycler.Handle<User> handler;

    public User(Recycler.Handle<User> handler) {
        this.handler = handler;
    }

    public Recycler.Handle<User> getHandler() {
        return handler;
    }
}

public class RecyclerTest {

    private static final Recycler<User> USER_RECYCLER = new Recycler<User>() {
        @Override
        protected User newObject(Handle<User> handle) {
            // 新建对象
            return new User(handle);
        }
    };

    public static void main(String[] args) {
        // 从对象池中获取对象
        User user1 = USER_RECYCLER.get();
        System.out.println(user1);

        // 从对象池中获取对象
        User user2 = USER_RECYCLER.get();
        System.out.println(user2);

        // 回收对象 user1
        user1.getHandler().recycle(user1);

        // 再次对象池中获取对象
        User user3 = USER_RECYCLER.get();
        System.out.println(user3);
        
        System.out.println("user1 == user3:" + (user1 == user3));
    }
}

在该实例中我们先从对象池中获取两个对象 user1、user2,由于这个时候 Recycler 中并没有对象,所以它会调用 Recycler 的 newObject() 创建一个新的 User 对象,然后我们再对对象 user1 进行回收,最后再从 Recycler 获取对象 user3,理论上来说 user1 == user3,我们看运行结果:

com.sike.netty.jinjie.bytebuf.recycler.User@36f0f1be
com.sike.netty.jinjie.bytebuf.recycler.User@157632c9
com.sike.netty.jinjie.bytebuf.recycler.User@36f0f1be
user1 == user3:true

运行结果与我们预想的一模一样。

从上面示例我们可以看出,利用 Recycler 我们可以实现对象的回收和再利用。所以我们可以将其当做一个工具类在项目中使用,当然并不是所有场景都可以使用它,我们应该结合实际情况。一般来说符合如下条件,可以使用对象池:

  1. 对象创建开销大,且可以重复使用。我们要注意:并不是所有对象都可以重复利用的
  2. 对象池的数量需要控制在可以接受的范围内,不能够无限膨胀。

复杂的老版本设计

我们先看 4.1.71 版本以前的设计,目前网上几乎所有 Recycler 的分析文章都是基于 4.1.71 之前的版本,所以大明哥先对之前的版本的设计做一个详细介绍,然后再介绍新版本,看看两者之间的实现差异。

我们先看它的内部结构图:

从图中可以看出它有三个核心组件:

  • Stack
  • DefaultHandle
  • WeakOrderQueue

下面大明哥一一介绍这些组件。

  • Stack
  • 点赞