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