diff --git a/.artifacts b/.artifacts index 6565cbab5cb..a5f400f416d 100644 --- a/.artifacts +++ b/.artifacts @@ -140,3 +140,4 @@ dubbo-plugin-context dubbo-plugin-classloader-filter dubbo-plugin-proxy-bytebuddy dubbo-plugin-qos-trace +dubbo-plugin-loom diff --git a/dubbo-plugin/dubbo-plugin-loom/pom.xml b/dubbo-plugin/dubbo-plugin-loom/pom.xml new file mode 100644 index 00000000000..ba865fe8a69 --- /dev/null +++ b/dubbo-plugin/dubbo-plugin-loom/pom.xml @@ -0,0 +1,48 @@ + + + + + org.apache.dubbo + dubbo-plugin + ${revision} + ../pom.xml + + 4.0.0 + + com.aliyun.dubbo + dubbo-plugin-loom + + + 21 + 21 + UTF-8 + UTF-8 + false + + + + + org.apache.dubbo + dubbo-common + ${project.version} + true + + + diff --git a/dubbo-plugin/dubbo-plugin-loom/src/main/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPool.java b/dubbo-plugin/dubbo-plugin-loom/src/main/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPool.java new file mode 100644 index 00000000000..c78c0b2b108 --- /dev/null +++ b/dubbo-plugin/dubbo-plugin-loom/src/main/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPool.java @@ -0,0 +1,42 @@ +/* + * 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 org.apache.dubbo.common.threadpool.support.loom; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.threadpool.ThreadPool; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_THREAD_NAME; +import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY; + +/** + * Creates a thread pool that use virtual thread + * + * @see Executors#newVirtualThreadPerTaskExecutor() + */ +public class VirtualThreadPool implements ThreadPool { + @Override + public Executor getExecutor(URL url) { + String name = url.getParameter(THREAD_NAME_KEY, (String) url.getAttribute(THREAD_NAME_KEY, DEFAULT_THREAD_NAME)); + return Executors.newThreadPerTaskExecutor( + Thread.ofVirtual() + .name(name, 1) + .factory()); + } +} diff --git a/dubbo-plugin/dubbo-plugin-loom/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.threadpool.ThreadPool b/dubbo-plugin/dubbo-plugin-loom/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.threadpool.ThreadPool new file mode 100644 index 00000000000..e9f3348ad45 --- /dev/null +++ b/dubbo-plugin/dubbo-plugin-loom/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.threadpool.ThreadPool @@ -0,0 +1 @@ +virtual=org.apache.dubbo.common.threadpool.support.loom.VirtualThreadPool diff --git a/dubbo-plugin/dubbo-plugin-loom/src/test/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPoolTest.java b/dubbo-plugin/dubbo-plugin-loom/src/test/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPoolTest.java new file mode 100644 index 00000000000..42653cd8bd4 --- /dev/null +++ b/dubbo-plugin/dubbo-plugin-loom/src/test/java/org/apache/dubbo/common/threadpool/support/loom/VirtualThreadPoolTest.java @@ -0,0 +1,66 @@ +/* + * 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 org.apache.dubbo.common.threadpool.support.loom; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.threadpool.ThreadPool; + +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledForJreRange; +import org.junit.jupiter.api.condition.JRE; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; + +import static org.apache.dubbo.common.constants.CommonConstants.QUEUES_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class VirtualThreadPoolTest { + + @Test + @EnabledForJreRange(min = JRE.JAVA_21) + void getExecutor1() throws Exception { + URL url = URL.valueOf("dubbo://10.20.130.230:20880/context/path?" + + THREAD_NAME_KEY + "=demo"); + ThreadPool threadPool = new VirtualThreadPool(); + Executor executor = threadPool.getExecutor(url); + + final CountDownLatch latch = new CountDownLatch(1); + executor.execute(() -> { + Thread thread = Thread.currentThread(); + assertTrue(thread.isVirtual()); + assertThat(thread.getName(), startsWith("demo")); + latch.countDown(); + }); + + latch.await(); + assertThat(latch.getCount(), is(0L)); + } + + @Test + @EnabledForJreRange(min = JRE.JAVA_21) + void getExecutor2() { + URL url = URL.valueOf("dubbo://10.20.130.230:20880/context/path?" + QUEUES_KEY + "=1"); + ThreadPool threadPool = new VirtualThreadPool(); + assertThat(threadPool.getExecutor(url).getClass().getName(), Matchers.is("java.util.concurrent.ThreadPerTaskExecutor")); + } +} diff --git a/dubbo-plugin/pom.xml b/dubbo-plugin/pom.xml index a7cf59881f0..e919be86f28 100644 --- a/dubbo-plugin/pom.xml +++ b/dubbo-plugin/pom.xml @@ -63,4 +63,16 @@ test + + + + loom + + [21,) + + + dubbo-plugin-loom + + + diff --git a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java index c150a71088b..6059919675c 100644 --- a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java +++ b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java @@ -51,6 +51,7 @@ class FileTest { ignoredModules.add(Pattern.compile("dubbo-core-spi")); ignoredModules.add(Pattern.compile("dubbo-demo.*")); ignoredModules.add(Pattern.compile("dubbo-annotation-processor")); + ignoredModules.add(Pattern.compile("dubbo-plugin-loom.*")); ignoredArtifacts.add(Pattern.compile("dubbo-demo.*")); ignoredArtifacts.add(Pattern.compile("dubbo-test.*"));