/* * Copyright 2013 The Netty Project * * The Netty Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package io.netty.util; import java.util.IdentityHashMap; import java.util.Map; /** * Light-weight object pool based on a thread-local stack. * * @param <T> the type of the pooled object */ public abstract class Recycler<T> { private final ThreadLocal<Stack<T>> threadLocal = new ThreadLocal<Stack<T>>() { @Override protected Stack<T> initialValue() { return new Stack<T>(Recycler.this, Thread.currentThread()); } }; //从threadLocal中弹出存放的元素 public final T get() { Stack<T> stack = threadLocal.get(); T o = stack.pop(); if (o == null) { o = newObject(stack); } return o; } /** * 判断传入的handle即stack对象,是否是可以循环利用的,判断条件为: * 1.检查handle所属的parent是否是当前对象 * 2.检查handle所属的线程是否是当前runtime线程 * 如果1,2条件都满足,则把元素push到handle中去 */ public final boolean recycle(T o, Handle handle) { @SuppressWarnings("unchecked") Stack<T> stack = (Stack<T>) handle; //检查handle里面的parent对象是否是当前对象 if (stack.parent != this) { return false; } //检查当前runtime线程是否是初始化handle的线程 if (Thread.currentThread() != stack.thread) { return false; } stack.push(o); return true; } protected abstract T newObject(Handle handle); public interface Handle { } static final class Stack<T> implements Handle { private static final int INITIAL_CAPACITY = 256; final Recycler<T> parent; final Thread thread; //初始化Stack对象的线程对象 private T[] elements; //存放元素的数组 private int size; //elements数组中已被赋值的元素中最后一个元素的索引+1即下一个待填元素的索引 //该Map主要用来检查Stack中是否有重复元素 private final Map<T, Boolean> map = new IdentityHashMap<T, Boolean>(INITIAL_CAPACITY); @SuppressWarnings({"unchecked", "SuspiciousArrayCast"}) Stack(Recycler<T> parent, Thread thread) { this.parent = parent; this.thread = thread; //初始化数组 elements = newArray(INITIAL_CAPACITY); } //弹出元素 T pop() { int size = this.size; //检查elements中是否有元素,没有元素则直接返回null if (size == 0) { return null; } //索引-1 size--; //从数组中取出元素 T ret = elements[size]; //将当前位置置为null elements[size] = null; //从map中删除该元素 map.remove(ret); this.size = size; return ret; } //往Stack中压入元素 void push(T o) { /** * 使用map.put方法,当put的key-value已存在时,put返回的值不为null * 这里检查添加已存在的值时,thow异常 */ if (map.put(o, Boolean.TRUE) != null) { throw new IllegalStateException("recycled already"); } int size = this.size; /** * 检查elements数组容器中已被赋值元素的最大个数,如果发现elements容器已经被填满 * 则把elements数组扩容,扩容的长度是:size*2 * 然后再把旧的elements元素复制到新的数组中去 */ if (size == elements.length) { T[] newElements = newArray(size << 1); System.arraycopy(elements, 0, newElements, 0, size); elements = newElements; } //把新添加的元素赋值到elements数组 elements[size] = o; //索引+1 this.size = size + 1; } @SuppressWarnings({"unchecked", "SuspiciousArrayCast"}) private static <T> T[] newArray(int length) { return (T[]) new Object[length]; } } }