netty-recycler,带你从设计层面完全了解它

271 阅读11分钟

netty-recycler,带你从设计层面完全了解它

我在初学recycler的时候看了不少文章,这些文章基本都写得不错,介绍的非常详细,recycler里面的组件也基本都介绍了,但是我在看的时候一直在想他引入这么多组件,设计这么复杂是为了什么,后面我终于搞懂了,所以分享给大家~

v1版本的recycler

import java.util.LinkedList;
import java.util.Stack;

public abstract class RecyclerV1<T> {

    private LinkedList<T> stack = new LinkedList();
//    private Stack<T> stack = new Stack();

    public final T get() {
        if(stack.isEmpty()){
            return newObject();
        }
        return stack.pop();
    }

    public final void recycle(T object) {
        stack.push(object);
    }

    protected abstract T newObject();

}
public class User {

    private RecyclerV1 recyclerV1;

    public User(RecyclerV1 recyclerV1){
        this.recyclerV1 = recyclerV1;
    }

    public void recycle() {
        recyclerV1.recycle(this);
    }

}
import org.junit.jupiter.api.Test;

public class TestRecyclerV1 {

    private static RecyclerV1<User> newRecycler() {
        return new RecyclerV1<User>() {
            @Override
            protected User newObject() {
                return new User(this);
            }
        };
    }

    public static void main(String[] args) {
        RecyclerV1<User> recycler = newRecycler();
        User user = recycler.get();

        user.recycle();

        User user2 = recycler.get();
        System.out.println(user==user2);
    }

    /**
     * 多线程get可能会错误, 线程不安全
     */
    @Test
    public void testGetError(){
        RecyclerV1<User> recycler = newRecycler();
        User user = recycler.get();
        user.recycle();

        for(int i=0;i<10;i++){
            new Thread(()->{
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                recycler.get();
            }).start();
        }
    }

    @Test
    public void testRepeatRecycler() {
        RecyclerV1<User> recycler = newRecycler();
        User user = recycler.get();

        //同一个对象不能回收多次
        user.recycle();
        user.recycle();
    }

}

这个版本的recycler有几个严重的bug:

  1. 其一是RecyclerV1#get函数,由于线程竞争,可能导致pop产生NoSuchElementException异常。
  2. 其二是RecyclerV1#recycle函数,同一个对象可以回收多次。

下面我们将逐渐修复这些bug

v2版本的recycler

在这个版本我将修复重复回收对象的问题,要想解决这个问题,我们就得知道对象有没有被回收,如果已经被回收了,我们就报一个错误recycled already。我们需要对对象包装一层。即用DefaultHandle包装对象。并且记录一个recyclerId标记回收对象的线程是谁。代码如下:

import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;

public abstract class RecyclerV2<T> {

    private LinkedList<DefaultHandle> stack = new LinkedList();
//    private Stack<T> stack = new Stack();

    public final T get() {
        if(stack.isEmpty()){
            DefaultHandle<T> handle = new DefaultHandle(stack);
            T value = newObject(handle);
            handle.value = value;
            return value;
        }
        return (T) stack.pop().value;
    }


    protected abstract T newObject(Handle<T> handle);



    public interface Handle<T> {
        void recycle(T self);
    }

    private static final class DefaultHandle<T> implements Handle<T>{
        T value;
        volatile long recyclerId;
        private LinkedList<DefaultHandle> stack;


        public DefaultHandle(LinkedList<DefaultHandle> stack){
            this.stack = stack;
        }

        private static final AtomicLongFieldUpdater<DefaultHandle<?>> RECYCLER_ID_UPDATER;
        static {
            AtomicLongFieldUpdater<?> updater = AtomicLongFieldUpdater.newUpdater(
                    DefaultHandle.class, "recyclerId");
            RECYCLER_ID_UPDATER = (AtomicLongFieldUpdater<DefaultHandle<?>>) updater;
        }

        @Override
        public final void recycle(T object) {
            if (object != value) {
                throw new IllegalArgumentException("object does not belong to handle");
            }
            if(recyclerId!=0){
                throw new IllegalStateException("recycled already");
            }
            if(!RECYCLER_ID_UPDATER.compareAndSet(this,0,Thread.currentThread().getId())){
                throw new IllegalStateException("recycled already");
            }

            stack.push(this);
        }

    }
}
public class User {

    private RecyclerV2.Handle handle;

    public User(RecyclerV2.Handle handle){
        this.handle = handle;
    }

    public void recycle() {
        handle.recycle(this);
    }

}

import org.junit.jupiter.api.Test;

public class TestRecyclerV2 {

    private static RecyclerV2<User> newRecycler() {
        return new RecyclerV2<User>() {
            @Override
            protected User newObject(RecyclerV2.Handle handle) {
                return new User(handle);
            }
        };
    }

    public static void main(String[] args) {
        RecyclerV2<User> recycler = newRecycler();
        User user = recycler.get();

        user.recycle();

        User user2 = recycler.get();
        System.out.println(user==user2);
    }

    /**
     * 多线程get可能会错误, 线程不安全
     */
    @Test
    public void testGetError(){
        RecyclerV2<User> recycler = newRecycler();
        User user = recycler.get();
        user.recycle();

        for(int i=0;i<10;i++){
            new Thread(()->{
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                recycler.get();
            }).start();
        }
    }

    @Test
    public void testRepeatRecycler() {
        RecyclerV2<User> recycler = newRecycler();
        User user = recycler.get();

        //同一个对象不能回收多次
        user.recycle();
        user.recycle();
    }


}

在这个版本里我把recycle方法放到了新建的内部类DefaultHandle里面,并且对recycleId做了volatile和cas处理来保证回收对象的线程安全特性。但是我们依然没有解决get函数由于线程竞争导致的pop NoSuchElementE xception, 其实我们把LinkedList换成线程安全的Stack即可解决。

tips: stack内部采用Syncronzied,效率较低,netty没有采用这种办法,而是采用了ThreadLocal来解决这个问题。

v3版本的recycler

v2版本我们解决了对象重复回收的bug,v3版本我们来思考下如何解决get函数由于线程竞争导致的pop NoSuchElementException。改动代码如下:

import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;

public abstract class RecyclerV3<T> {

    private ThreadLocal<LinkedList<DefaultHandle>> threadLocal = new ThreadLocal<LinkedList<DefaultHandle>>(){
        @Override
        protected LinkedList<DefaultHandle> initialValue() {
            return new LinkedList();
        }
    };


    public final T get() {
        LinkedList<DefaultHandle> stack = threadLocal.get();

        if(stack.isEmpty()){
            DefaultHandle<T> handle = new DefaultHandle(stack);
            T value = newObject(handle);
            handle.value = value;
            return value;
        }

        return (T) stack.pop().value;
    }


    protected abstract T newObject(Handle<T> handle);
    
    
    public int size(){
        return threadLocal.get().size();
    }
    
    public interface Handle<T> {
        void recycle(T self);
    }

    private static final class DefaultHandle<T> implements Handle<T>{
        T value;
        volatile long recyclerId;
        private LinkedList<DefaultHandle> stack;


        public DefaultHandle(LinkedList<DefaultHandle> stack){
            this.stack = stack;
        }

        private static final AtomicLongFieldUpdater<DefaultHandle<?>> RECYCLER_ID_UPDATER;
        static {
            AtomicLongFieldUpdater<?> updater = AtomicLongFieldUpdater.newUpdater(
                    DefaultHandle.class, "recyclerId");
            RECYCLER_ID_UPDATER = (AtomicLongFieldUpdater<DefaultHandle<?>>) updater;
        }

        @Override
        public final void recycle(T object) {
            if (object != value) {
                throw new IllegalArgumentException("object does not belong to handle");
            }
            if(recyclerId!=0){
                throw new IllegalStateException("recycled already");
            }
            if(!RECYCLER_ID_UPDATER.compareAndSet(this,0,Thread.currentThread().getId())){
                throw new IllegalStateException("recycled already");
            }

            stack.push(this);
        }

    }
}

在v3版本的代码里,我为每个线程分配了一个stack,这样自然就避免了get函数线程竞争,也就解决get函数的bug。但是这样处理带来了一个问题,注意看DefalultHandle的stack属性,它其实是创建线程的stack,当不同线程调用recycle函数时,他们都是使用stack来push,这里会有竞争,即非线程安全。

@Test
public void testRecycleByOtherThread() throws IOException, InterruptedException {
    RecyclerV3<User> recycler = newRecycler();
    List<User> users = new ArrayList<>();
    for(int i=0;i<10;i++){
        User user = recycler.get();//main线程创建的对象
        users.add(user);
    }

    for (User user : users) {
        new Thread(()->{
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            user.recycle();
        }).start();
    }

    Thread.sleep(1000);
    System.out.println(recycler.size());
}

执行结果如下:

图片.png

v4版本的recycler

v3版本我们解决了get函数的竞争,但是导致了recycle函数的竞争,下面我们不妨删除DefalultHandle的stack,stack统一从threadlocal中拿。

public abstract class RecyclerV4<T> {

    private ThreadLocal<LinkedList<DefaultHandle>> threadLocal = new ThreadLocal<LinkedList<DefaultHandle>>(){
        @Override
        protected LinkedList<DefaultHandle> initialValue() {
            return new LinkedList();
        }
    };


    public final T get() {
        LinkedList<DefaultHandle> stack = threadLocal.get();

        if(stack.isEmpty()){
            DefaultHandle<T> handle = new DefaultHandle();
            T value = newObject(handle);
            handle.value = value;
            return value;
        }

        return (T) stack.pop().value;
    }


    protected abstract T newObject(Handle<T> handle);



    public interface Handle<T> {
        void recycle(T self);
    }

    private final class DefaultHandle<T> implements Handle<T>{
        T value;
        volatile long recyclerId;//记录回收value的线程id


        private final AtomicLongFieldUpdater<DefaultHandle<?>> RECYCLER_ID_UPDATER;
        {
            AtomicLongFieldUpdater<?> updater = AtomicLongFieldUpdater.newUpdater(
                    DefaultHandle.class, "recyclerId");
            RECYCLER_ID_UPDATER = (AtomicLongFieldUpdater<DefaultHandle<?>>) updater;
        }

        @Override
        public final void recycle(T object) {
            if (object != value) {
                throw new IllegalArgumentException("object does not belong to handle");
            }
            if(recyclerId!=0){
                throw new IllegalStateException("recycled already");
            }
            if(!RECYCLER_ID_UPDATER.compareAndSet(this,0,Thread.currentThread().getId())){
                throw new IllegalStateException("recycled already");
            }

            LinkedList<DefaultHandle> stack = threadLocal.get();
            stack.push(this);
        }

    }
}

在代码里,我为每个线程分配了一个stack,这样自然就避免了get和recycle函数线程竞争,但是这样处理带来了一个更大的问题,由于之前所有线程共享一个stack,不管哪个线程过来回收都是回收到这个共享stack中。但我们现在为每个线程分配了一个stack,问题就变得有趣起来了。让我们来分析下面这个例子:

@Test
public void testRecycleByOtherThread() throws InterruptedException {
    RecyclerV3<User> recycler = newRecycler();
    User user = recycler.get();//main线程创建的对象


    Thread t = new Thread(()->{
        user.recycle();//由线程t回收到自己的stack
    });
    
    t.start();
    t.join();
    
    User user2 = recycler.get();
    System.out.println(user == user2);//始终是false
}

现在每个线程都有一个stack,main线程创建的线程被t线程回收到t线程的stack去了,所以后面main线程再来get得到的对象又是一个新创建的对象。

tips: 上面这样是不符合我们的预期的,我们希望不管回收对象的线程是谁,哪个线程创建的对象最终也会被回收这个线程去。像上面这种情况,t线程把对象回收到自己的stack中但是线程立马就死了,那这个对象相当于被浪费了。

v5版本的recycler

在v4版本中我们解决了v1提出的两个bug,但是引出了一个更大bug:线程main创建的对象没有回收到main线程的stack。从v3版本和v4版本回收对象的时候可以看出:既不能回收到共享stack,也不能回收到各自线程的stack。

如何解决这个问题?

我们可以把存储对象的容器分开来,stack存储创建线程回收的对象,otherStack存储其他线程帮助创建线程回收的对象。回收的时候判断当前线程是不是创建线程,是的话直接回收到stack中,不是的话回收到otherStack(注意每个回收线程对应一个otherStack,所以不会有竞争)。然后get的时候再从otherStack收割对象到stack中。

import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;

public abstract class RecyclerV5<T> {

    private ThreadLocal<Stack<T>> threadLocal = new ThreadLocal<Stack<T>>(){
        @Override
        protected Stack<T> initialValue() {
            return new Stack<>();
        }
    };


    public final T get() {
        Stack<T> stack = threadLocal.get();

        DefaultHandle<T> handle = stack.pop();

        if(null==handle){
            handle = new DefaultHandle(stack);
            T value = newObject(handle);
            handle.value = value;
        }

        return handle.value;
    }


    protected abstract T newObject(Handle<T> handle);



    private final class Stack<T>{
        //创建线程的对象栈
        LinkedList<DefaultHandle<T>> stack = new LinkedList<>();

        //创建线程
        final WeakReference<Thread> threadRef;

        //其他线程帮创建线程回收的对象
        Map<Thread,LinkedList<DefaultHandle<T>>> otherStackMap = new WeakHashMap<>();

        public Stack(){
            threadRef = new WeakReference(Thread.currentThread());
        }


        public boolean isEmpty(){
            return stack.isEmpty();
        }

        public DefaultHandle<T> pop(){
            if(isEmpty()){
                scavenge();
            }
            if(isEmpty()){
                return null;
            }
            return stack.pop();
        }


        public void scavenge(){
            //todo bug
            for (LinkedList<DefaultHandle<T>> value : otherStackMap.values()) {
                stack.addAll(value);
            }
        }

        public void push(DefaultHandle<T> handle){
            //当前回收线程是谁
            Thread recycleThread = Thread.currentThread();

            //创建线程已死则不需要回收了
            if(null==threadRef.get()){
                return;
            }

            //创建线程和回收线程是同一个
            if (threadRef.get() == recycleThread) {
                pushNow(handle);
            }else{
                pushLater(handle);
            }
        }

        private void pushNow(DefaultHandle<T> handle){
            stack.push(handle);
        }


        /**
         * 其他线程帮助回收 创建线程创建的对象,涉及到多线程竞争
         * @param handle
         */
        private void pushLater(DefaultHandle<T> handle){
            Thread recycleThread = Thread.currentThread();

            LinkedList<DefaultHandle<T>> stack = otherStackMap.getOrDefault(recycleThread,new LinkedList<>());

            stack.push(handle);

            otherStackMap.put(recycleThread,stack);
        }

    }

    public interface Handle<T> {
        void recycle(T self);
    }

    private final class DefaultHandle<T> implements Handle<T>{
        T value;
        volatile long recyclerId;//记录回收value的线程id
        private Stack<T> stack;

        public DefaultHandle(Stack<T> stack) {
            this.stack = stack;
        }

        private final AtomicLongFieldUpdater<DefaultHandle<?>> RECYCLER_ID_UPDATER;
        {
            AtomicLongFieldUpdater<?> updater = AtomicLongFieldUpdater.newUpdater(
                    DefaultHandle.class, "recyclerId");
            RECYCLER_ID_UPDATER = (AtomicLongFieldUpdater<DefaultHandle<?>>) updater;
        }

        @Override
        public final void recycle(T object) {
            if (object != value) {
                throw new IllegalArgumentException("object does not belong to handle");
            }
            if(recyclerId!=0){
                throw new IllegalStateException("recycled already");
            }
            if(!RECYCLER_ID_UPDATER.compareAndSet(this,0,Thread.currentThread().getId())){
                throw new IllegalStateException("recycled already");
            }
            stack.push(this);
        }

    }
}
public class User {

    private RecyclerV5.Handle handle;

    public User(RecyclerV5.Handle handle){
        this.handle = handle;
    }

    public void recycle() {
        handle.recycle(this);
    }

}
import org.testng.annotations.Test;

import java.util.HashMap;
import java.util.Map;

public class TestRecyclerV5 {

    private static RecyclerV5<User> newRecycler() {
        return new RecyclerV5<User>() {
            @Override
            protected User newObject(Handle handle) {
                return new User(handle);
            }
        };
    }

   
    private void t(User user) throws InterruptedException {
        Thread t = new Thread(()->{
            user.recycle();//由线程a回收到自己的stack
        });
        t.start();
        t.join();
    }

    @Test
    public void testRecycleByOtherThread() throws InterruptedException {
        RecyclerV5<User> recycler = newRecycler();
        User user = recycler.get();//main线程创建的对象


        t(user);
        System.gc();//gc 会清除otherStack,这行注释掉下面就是true了

        User user2 = recycler.get();
        System.out.println(user == user2);//始终是false
    }
   
}

在这个版本的代码中我引入了自己的Stack组件,储存了stack,otherStackMap以及创建线程threadRef。push的时候我会判断回收线程是否是创建线程是的话回收到stack,不是的话回收到otherStackMap。pop的时候如果stack是空,则先从otherStackMap收割对象。

这个版本的代码有个bug,scavenge函数是有问题的,试想当创建线程在scavenge遍历otherStackMap时,其他回收线程也可能往这个map里put元素,导致ConcurrentModifyException。在netty源码中又引入了WeakOrderQueue和Link组件去解决这个问题。

v6版本的recycler

这个版本我引入了WeakOrderQueue和Link组件来解决v5版本遗留的bug。

import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;

public abstract class RecyclerV6<T> {

    private ThreadLocal<Stack<T>> threadLocal = new ThreadLocal<Stack<T>>(){
        @Override
        protected Stack<T> initialValue() {
            return new Stack<>();
        }
    };
    private static final int LINK_CAPACITY = 16;//16

    private static final ThreadLocal<Map<Stack<?>, WeakOrderQueue>> DELAYED_RECYCLED =
            new ThreadLocal<Map<Stack<?>, WeakOrderQueue>>() {
                @Override
                protected Map<Stack<?>, WeakOrderQueue> initialValue() {
                    return new WeakHashMap<Stack<?>, WeakOrderQueue>();
                }
            };

    public final T get() {
        Stack<T> stack = threadLocal.get();

        DefaultHandle<T> handle = stack.pop();

        if(null==handle){
            handle = new DefaultHandle(stack);
            T value = newObject(handle);
            handle.value = value;
        }

        return handle.value;
    }


    protected abstract T newObject(Handle<T> handle);

    private static final class WeakOrderQueue extends WeakReference<Thread> {

        private final Link head;
        private Link tail;
        private WeakOrderQueue next;

        private WeakOrderQueue() {
            super(null);
            head = new Link();
        }

        private WeakOrderQueue(Stack<?> stack, Thread thread) {
            super(thread);
            head = new Link();
            tail = head;
        }

        public static <T> WeakOrderQueue newQueue(Stack stack, Thread recycleThread) {
            final WeakOrderQueue queue = new WeakOrderQueue(stack, recycleThread);
            stack.setHead(queue);
            return queue;
        }

        public <T> void add(DefaultHandle<T> handle) {
            Link tail = this.tail;
            int writeIndex;

            //最后一个link写满了,新建link
            if ((writeIndex = tail.get()) == LINK_CAPACITY) {
                Link link = new Link();

                // We allocate a Link so reserve the space
                this.tail = tail = tail.next = link;

                writeIndex = tail.get();
            }
            tail.elements[writeIndex] = handle;
            handle.stack = null;
            // we lazy set to ensure that setting stack to null appears before we unnull it in the owning thread;
            // this also means we guarantee visibility of an element in the queue if we see the index updated
            tail.lazySet(writeIndex + 1);
        }

        public void setNext(WeakOrderQueue next) {
            this.next = next;
        }

        public <T> boolean transfer(Stack<T> stack) {
            final int srcStart = head.readIndex;
            int srcEnd = head.get();
            final int srcSize = srcEnd - srcStart;
            if (srcSize == 0) {
                return false;
            }

            final DefaultHandle[] srcElems = head.elements;
            for (int i = srcStart; i < srcEnd; i++) {
                DefaultHandle<T> element = srcElems[i];
                srcElems[i] = null;
                stack.pushNow(element);
            }

            head.readIndex = srcEnd;
            return true;
        }

        public WeakOrderQueue getNext() {
            return next;
        }

        final class Link extends AtomicInteger {
            final DefaultHandle<?>[] elements = new DefaultHandle[LINK_CAPACITY];
            int readIndex;
            Link next;
        }


    }

    private static final class Stack<T>{
        //创建线程的对象栈
        LinkedList<DefaultHandle<T>> stack = new LinkedList<>();

        private volatile WeakOrderQueue head;
        private WeakOrderQueue cursor,prev;

        //创建线程
        final WeakReference<Thread> threadRef;

        public Stack(){
            threadRef = new WeakReference(Thread.currentThread());
        }


        public boolean isEmpty(){
            return stack.isEmpty();
        }

        public DefaultHandle<T> pop(){
            if(isEmpty()){
                scavenge();
            }
            if(isEmpty()){
                return null;
            }
            return stack.pop();
        }

        private boolean scavenge() {
            // continue an existing scavenge, if any
            if (scavengeSome()) {
                return true;
            }

            // reset our scavenge cursor
            prev = null;
            cursor = head;
            return false;
        }

        public boolean scavengeSome(){
            WeakOrderQueue cursor = this.cursor;
            WeakOrderQueue prev;
            if(null==cursor){
                prev = null;
                cursor = head;
                if (cursor == null) {
                    return false;
                }
            }else{
                prev = this.prev;
            }
            boolean success = false;

            do {
                //当前游标的WeakOrderQueue收割成功直接return
                if (cursor.transfer(this)) {
                    success = true;
                    break;
                }
                WeakOrderQueue next = cursor.getNext();

                //回收线程已死
                if (cursor.get() == null) {
                    // If the thread associated with the queue is gone, unlink it, after
                    // performing a volatile read to confirm there is no data left to collect.
                    // We never unlink the first queue, as we don't want to synchronize on updating the head.
                    for (;;) {
                        if (cursor.transfer(this)) {
                            success = true;
                        } else {
                            break;
                        }
                    }

                    if (prev != null) {
                        // prev!=null说明cursor不指向头节点,因此要将cursor指向的节点移出链表
                        prev.setNext(next);
                    }
                } else {
                    prev = cursor;
                }

                cursor = next;

            } while (cursor != null && !success);

            this.prev = prev;
            this.cursor = cursor;
            return success;
        }

        public void push(DefaultHandle<T> handle){
            //当前回收线程是谁
            Thread recycleThread = Thread.currentThread();

            //创建线程已死则不需要回收了
            if(null==threadRef.get()){
                return;
            }

            //创建线程和回收线程是同一个
            if (threadRef.get() == recycleThread) {
                pushNow(handle);
            }else{
                pushLater(handle);
            }
        }

        public void pushNow(DefaultHandle<T> handle){
            stack.push(handle);
        }


        /**
         * 其他线程帮助回收 创建线程创建的对象,涉及到多线程竞争
         * @param handle
         */
        private void pushLater(DefaultHandle<T> handle){
            Thread recycleThread = Thread.currentThread();

            //创建线程的栈,某个回收线程对应的节点
            Map<Stack<?>, WeakOrderQueue> delayedRecycled = DELAYED_RECYCLED.get();

            //某个回收线程对应的节点
            WeakOrderQueue queue = delayedRecycled.get(this);
            if(null==queue){
                if ((queue = newWeakOrderQueue(recycleThread)) == null) {
                    return;
                }
                delayedRecycled.put(this, queue);
            }
            queue.add(handle);
        }

        private WeakOrderQueue newWeakOrderQueue(Thread recycleThread) {
            return WeakOrderQueue.newQueue(this, recycleThread);
        }

        synchronized void setHead(WeakOrderQueue queue) {
            queue.setNext(head);
            head = queue;
        }
    }

    public interface Handle<T> {
        void recycle(T self);
    }

    private static final class DefaultHandle<T> implements Handle<T>{
        T value;
        volatile long recyclerId;//记录回收value的线程id
        private Stack<T> stack;

        public DefaultHandle(Stack<T> stack) {
            this.stack = stack;
        }

        private final AtomicLongFieldUpdater<DefaultHandle<?>> RECYCLER_ID_UPDATER;
        {
            AtomicLongFieldUpdater<?> updater = AtomicLongFieldUpdater.newUpdater(
                    DefaultHandle.class, "recyclerId");
            RECYCLER_ID_UPDATER = (AtomicLongFieldUpdater<DefaultHandle<?>>) updater;
        }

        @Override
        public final void recycle(T object) {
            if (object != value) {
                throw new IllegalArgumentException("object does not belong to handle");
            }
            if(recyclerId!=0){
                throw new IllegalStateException("recycled already");
            }
            if(!RECYCLER_ID_UPDATER.compareAndSet(this,0,Thread.currentThread().getId())){
                throw new IllegalStateException("recycled already");
            }
            stack.push(this);
        }

    }
}

我迭代了6个版本说明了Recycler的设计思想以及引入这么多组件的目的,Recycler是一个非常轻量级的对象池,他希望不加任何锁实现它。关于为什么引入DefaultHandle,Stack,WeakOrderQueue,Link,相信您只要认真阅读过并且敲过这6个版本的代码,一定非常理解了。

参考

# Netty学习十四:内存管理之Recycler 对象池

# Netty源码解析(八)之Recycler

netty recycler bug