Fix bug in InternalThreadLocal and provides unit test (#1803)

* SerializerFactory 获取Serializer时,锁住整个hashmap,导致整个过程被block

* 单元测试。保证一个class只有一个serializer和deserializer。单线程和多线程测试

* 增加线程数 50 模拟多个线程来获取serializer和deserializer

* 当cores线程数全都使用的情况下,默认线程池会把任务放入到队列中。队列满则再创建线程(总数不会超过Max线程数)
增强线程池:在请求量阶段性出现高峰时使用
特性:cores线程全部使用的情况下,优先创建线程(总数不会超过max),当max个线程全都在忙的情况下,才将任务放入队列。请求量下降时,线程池会自动维持cores个线程,多余的线程退出。

* 当cores线程数全都使用的情况下,默认线程池会把任务放入到队列中。队列满则再创建线程(总数不会超过Max线程数)
增强线程池:在请求量阶段性出现高峰时使用
特性:cores线程全部使用的情况下,优先创建线程(总数不会超过max),当max个线程全都在忙的情况下,才将任务放入队列。请求量下降时,线程池会自动维持cores个线程,多余的线程退出。

* 补全单元测试,测试扩展是否生效

* 错误命名

* 增加@Override注解
long 初始化赋值时,小写l改为大写L防止误读

* 修复单元测试

* remove enhanced

* remove enhanced

* Faster ThreadLocal impl in internal use
* Used in RpcContext`s LOCAL field.
* Faster get than the traditional ThreadLocal

* add License

* fix ci failed

* fix ci failed

* fix ci failed

* fix ci failed

* fix ci failed

* remove author info

* fix destroy method

* fix bug at method size.

* Unit test for InternalThreadLocal

* Unit test for InternalThreadLocal
Fix bug in method removeAll
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocal.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocal.java
index 4eed57c..d3d6489 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocal.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocal.java
@@ -58,7 +58,9 @@
             Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);
             if (v != null && v != InternalThreadLocalMap.UNSET) {
                 Set<InternalThreadLocal<?>> variablesToRemove = (Set<InternalThreadLocal<?>>) v;
-                for (InternalThreadLocal<?> tlv : variablesToRemove) {
+                InternalThreadLocal<?>[] variablesToRemoveArray =
+                        variablesToRemove.toArray(new InternalThreadLocal[variablesToRemove.size()]);
+                for (InternalThreadLocal<?> tlv : variablesToRemoveArray) {
                     tlv.remove(threadLocalMap);
                 }
             }
diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocalTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocalTest.java
index b0a8c28..401906e 100644
--- a/dubbo-common/src/test/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocalTest.java
+++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocalTest.java
@@ -62,6 +62,32 @@
     }
 
     @Test
+    public void testRemoveAll() throws InterruptedException {
+        final InternalThreadLocal<Integer> internalThreadLocal = new InternalThreadLocal<Integer>();
+        internalThreadLocal.set(1);
+        Assert.assertTrue("set failed", internalThreadLocal.get() == 1);
+
+        final InternalThreadLocal<String> internalThreadLocalString = new InternalThreadLocal<String>();
+        internalThreadLocalString.set("value");
+        Assert.assertTrue("set failed", "value".equals(internalThreadLocalString.get()));
+
+        InternalThreadLocal.removeAll();
+        Assert.assertTrue("removeAll failed!", internalThreadLocal.get() == null);
+        Assert.assertTrue("removeAll failed!", internalThreadLocalString.get() == null);
+    }
+
+    @Test
+    public void testSize() throws InterruptedException {
+        final InternalThreadLocal<Integer> internalThreadLocal = new InternalThreadLocal<Integer>();
+        internalThreadLocal.set(1);
+        Assert.assertTrue("size method is wrong!", InternalThreadLocal.size() == 1);
+
+        final InternalThreadLocal<String> internalThreadLocalString = new InternalThreadLocal<String>();
+        internalThreadLocalString.set("value");
+        Assert.assertTrue("size method is wrong!", InternalThreadLocal.size() == 2);
+    }
+
+    @Test
     public void testSetAndGet() {
         final Integer testVal = 10;
         final InternalThreadLocal<Integer> internalThreadLocal = new InternalThreadLocal<Integer>();
@@ -71,6 +97,33 @@
     }
 
     @Test
+    public void testRemove() {
+        final InternalThreadLocal<Integer> internalThreadLocal = new InternalThreadLocal<Integer>();
+        internalThreadLocal.set(1);
+        Assert.assertTrue("get method false!", internalThreadLocal.get() == 1);
+
+        internalThreadLocal.remove();
+        Assert.assertTrue("remove failed!", internalThreadLocal.get() == null);
+    }
+
+    @Test
+    public void testOnRemove() {
+        final Integer[] valueToRemove = {null};
+        final InternalThreadLocal<Integer> internalThreadLocal = new InternalThreadLocal<Integer>() {
+            @Override
+            protected void onRemoval(Integer value) throws Exception {
+                //value calculate
+                valueToRemove[0] = value + 1;
+            }
+        };
+        internalThreadLocal.set(1);
+        Assert.assertTrue("get method false!", internalThreadLocal.get() == 1);
+
+        internalThreadLocal.remove();
+        Assert.assertTrue("onRemove method failed!", valueToRemove[0] == 2);
+    }
+
+    @Test
     public void testMultiThreadSetAndGet() throws InterruptedException {
         final Integer testVal1 = 10;
         final Integer testVal2 = 20;
diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/threadlocal/NamedInternalThreadFactoryTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/threadlocal/NamedInternalThreadFactoryTest.java
new file mode 100644
index 0000000..5d80023
--- /dev/null
+++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/threadlocal/NamedInternalThreadFactoryTest.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 com.alibaba.dubbo.common.threadlocal;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class NamedInternalThreadFactoryTest {
+
+    @Test
+    public void newThread() throws Exception {
+        NamedInternalThreadFactory namedInternalThreadFactory = new NamedInternalThreadFactory();
+        Thread t = namedInternalThreadFactory.newThread(new Runnable() {
+            @Override
+            public void run() {
+
+            }
+        });
+        Assert.assertTrue("thread is not InternalThread", t.getClass().equals(InternalThread.class));
+    }
+}
\ No newline at end of file