This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit e5decc41fbf1be8285db1924b6f8384078225cdd Author: Mark Thomas <ma...@apache.org> AuthorDate: Fri May 12 17:30:27 2023 +0100 Add useVirtualThreads attribute to endpoints. Refactor VirtualThreadExecutor so it can be used by the Endpoint --- .../apache/catalina/core/LocalStrings.properties | 5 +-- ...tor.java => StandardVirtualThreadExecutor.java} | 23 +++++++------ .../apache/tomcat/util/net/AbstractEndpoint.java | 23 ++++++++++--- .../tomcat/util/threads/VirtualThreadExecutor.java | 40 ++++++++++++++++++++++ webapps/docs/changelog.xml | 4 +-- webapps/docs/config/ajp.xml | 7 ++++ webapps/docs/config/executor.xml | 4 +-- webapps/docs/config/http.xml | 7 ++++ 8 files changed, 93 insertions(+), 20 deletions(-) diff --git a/java/org/apache/catalina/core/LocalStrings.properties b/java/org/apache/catalina/core/LocalStrings.properties index 64fc860dac..47959993dd 100644 --- a/java/org/apache/catalina/core/LocalStrings.properties +++ b/java/org/apache/catalina/core/LocalStrings.properties @@ -286,6 +286,9 @@ standardService.stop.name=Stopping service [{0}] standardThreadExecutor.notStarted=The executor has not been started +standardVirtualThreadExecutor.notStarted=The executor has not been started +standardVirtualThreadExecutor.noVirtualThreads=Virtual threads require a minimum Java version of Java 21 + standardWrapper.allocate=Error allocating a servlet instance standardWrapper.allocateException=Allocate exception for servlet [{0}] standardWrapper.deallocateException=Deallocate exception for servlet [{0}] @@ -309,5 +312,3 @@ standardWrapper.waiting=Waiting for [{0}] instance(s) to be deallocated for Serv threadLocalLeakPreventionListener.containerEvent.error=Exception processing container event [{0}] threadLocalLeakPreventionListener.lifecycleEvent.error=Exception processing lifecycle event [{0}] - -virtualThreadExecutor.noVirtualThreads=Virtual threads require a minimum Java version of Java 21 \ No newline at end of file diff --git a/java/org/apache/catalina/core/VirtualThreadExecutor.java b/java/org/apache/catalina/core/StandardVirtualThreadExecutor.java similarity index 79% rename from java/org/apache/catalina/core/VirtualThreadExecutor.java rename to java/org/apache/catalina/core/StandardVirtualThreadExecutor.java index 496aeb3303..d9d584ee41 100644 --- a/java/org/apache/catalina/core/VirtualThreadExecutor.java +++ b/java/org/apache/catalina/core/StandardVirtualThreadExecutor.java @@ -24,18 +24,17 @@ import org.apache.catalina.LifecycleState; import org.apache.catalina.util.LifecycleMBeanBase; import org.apache.tomcat.util.compat.JreCompat; import org.apache.tomcat.util.res.StringManager; +import org.apache.tomcat.util.threads.VirtualThreadExecutor; /** * An executor that uses a new virtual thread for each task. */ -public class VirtualThreadExecutor extends LifecycleMBeanBase implements Executor { +public class StandardVirtualThreadExecutor extends LifecycleMBeanBase implements Executor { - private static final StringManager sm = StringManager.getManager(VirtualThreadExecutor.class); - - private final JreCompat jreCompat = JreCompat.getInstance(); + private static final StringManager sm = StringManager.getManager(StandardVirtualThreadExecutor.class); private String name; - private Object threadBuilder; + private java.util.concurrent.Executor executor; private String namePrefix; public void setName(String name) { @@ -57,13 +56,17 @@ public class VirtualThreadExecutor extends LifecycleMBeanBase implements Executo @Override public void execute(Runnable command) { - JreCompat.getInstance().threadBuilderStart(threadBuilder, command); + if (executor == null) { + throw new IllegalStateException(sm.getString("standardVirtualThreadExecutor.notStarted")); + } else { + executor.execute(command); + } } @Override public void execute(Runnable command, long timeout, TimeUnit unit) { - JreCompat.getInstance().threadBuilderStart(threadBuilder, command); + execute(command); } @@ -71,19 +74,19 @@ public class VirtualThreadExecutor extends LifecycleMBeanBase implements Executo protected void initInternal() throws LifecycleException { super.initInternal(); if (!JreCompat.isJre21Available()) { - throw new LifecycleException(sm.getString("virtualThreadExecutor.noVirtualThreads")); + throw new LifecycleException(sm.getString("standardVirtualThreadExecutor.noVirtualThreads")); } } @Override protected void startInternal() throws LifecycleException { - threadBuilder = jreCompat.createVirtualThreadBuilder(getNamePrefix()); + executor = new VirtualThreadExecutor(getNamePrefix()); setState(LifecycleState.STARTING); } @Override protected void stopInternal() throws LifecycleException { - threadBuilder = null; + executor = null; setState(LifecycleState.STOPPING); } diff --git a/java/org/apache/tomcat/util/net/AbstractEndpoint.java b/java/org/apache/tomcat/util/net/AbstractEndpoint.java index 0686b516a5..423403e31f 100644 --- a/java/org/apache/tomcat/util/net/AbstractEndpoint.java +++ b/java/org/apache/tomcat/util/net/AbstractEndpoint.java @@ -56,6 +56,7 @@ import org.apache.tomcat.util.threads.ResizableExecutor; import org.apache.tomcat.util.threads.TaskQueue; import org.apache.tomcat.util.threads.TaskThreadFactory; import org.apache.tomcat.util.threads.ThreadPoolExecutor; +import org.apache.tomcat.util.threads.VirtualThreadExecutor; /** * @param <S> The type used by the socket wrapper associated with this endpoint. @@ -629,6 +630,15 @@ public abstract class AbstractEndpoint<S,U> { public Executor getExecutor() { return executor; } + private boolean useVirtualThreads = false; + public void setUseVirtualThreads(boolean useVirtualThreads) { + this.useVirtualThreads = useVirtualThreads; + } + public boolean getVirtualThreads() { + return useVirtualThreads; + } + + /** * Server socket port. */ @@ -1064,12 +1074,17 @@ public abstract class AbstractEndpoint<S,U> { public void createExecutor() { internalExecutor = true; - TaskQueue taskqueue = new TaskQueue(); - TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority()); - executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf); - taskqueue.setParent( (ThreadPoolExecutor) executor); + if (useVirtualThreads) { + executor = new VirtualThreadExecutor(getName() + "-exec-"); + } else { + TaskQueue taskqueue = new TaskQueue(); + TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority()); + executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf); + taskqueue.setParent( (ThreadPoolExecutor) executor); + } } + public void shutdownExecutor() { Executor executor = this.executor; if (executor != null && internalExecutor) { diff --git a/java/org/apache/tomcat/util/threads/VirtualThreadExecutor.java b/java/org/apache/tomcat/util/threads/VirtualThreadExecutor.java new file mode 100644 index 0000000000..93a00f8d42 --- /dev/null +++ b/java/org/apache/tomcat/util/threads/VirtualThreadExecutor.java @@ -0,0 +1,40 @@ +/* + * 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.tomcat.util.threads; + +import java.util.concurrent.Executor; + +import org.apache.tomcat.util.compat.JreCompat; + +/** + * An executor that uses a new virtual thread for each task. + */ +public class VirtualThreadExecutor implements Executor { + + private final JreCompat jreCompat = JreCompat.getInstance(); + + private Object threadBuilder; + + public VirtualThreadExecutor(String namePrefix) { + threadBuilder = jreCompat.createVirtualThreadBuilder(namePrefix); + } + + @Override + public void execute(Runnable command) { + jreCompat.threadBuilderStart(threadBuilder, command); + } +} \ No newline at end of file diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 52b9fd2a5c..2c4aa6fc53 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -108,8 +108,8 @@ <subsection name="Catalina"> <changelog> <add> - Add <code>org.apache.catalina.core.VirtualThreadExecutor</code>, a - virtual thread based executor that may be used with one or more + Add <code>org.apache.catalina.core.StandardVirtualThreadExecutor</code>, + a virtual thread based executor that may be used with one or more Connectors to process requests received by those Connectors using virtual threads. This Executor requires a minimum Java version of Java 21. (markt) diff --git a/webapps/docs/config/ajp.xml b/webapps/docs/config/ajp.xml index 9436a766fe..8492451a2e 100644 --- a/webapps/docs/config/ajp.xml +++ b/webapps/docs/config/ajp.xml @@ -565,6 +565,13 @@ <code>false</code>.</p> </attribute> + <attribute name="useVirtualThreads" required="false"> + <p>(bool) Use this attribute to enable or disable usage of virtual threads + with the internal executor. If an executor is associated with this + connector, this attribute is ignored. The default value is + <code>false</code>.</p> + </attribute> + </attributes> </subsection> diff --git a/webapps/docs/config/executor.xml b/webapps/docs/config/executor.xml index 59cf023605..b5e48099f5 100644 --- a/webapps/docs/config/executor.xml +++ b/webapps/docs/config/executor.xml @@ -128,8 +128,8 @@ <p>This implemtenation uses a new virtual thread to execute each task assigned to the Executor. This Executor requires a minimum Java version of Java 21.</p> - <p>The <code>className</code> attribute must be <code>org.apache.catalina.core.VirtualThreadExecutor</code> to use - this implementation.</p> + <p>The <code>className</code> attribute must be <code>org.apache.catalina.core.StandardVirtualThreadExecutor</code> to + use this implementation.</p> <p>The virtual thread implementation supports the follow attributes:</p> diff --git a/webapps/docs/config/http.xml b/webapps/docs/config/http.xml index 6edee2ad81..ca53ac4f5f 100644 --- a/webapps/docs/config/http.xml +++ b/webapps/docs/config/http.xml @@ -741,6 +741,13 @@ Internet-Draft</a>. The default value is <code>true</code>.</p> </attribute> + <attribute name="useVirtualThreads" required="false"> + <p>(bool) Use this attribute to enable or disable usage of virtual threads + with the internal executor. If an executor is associated with this + connector, this attribute is ignored. The default value is + <code>false</code>.</p> + </attribute> + </attributes> </subsection> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org