/* * Copyright 2002-2018 the original author or authors. * * Licensed 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.springframework.scheduling.concurrent; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.Future; import javax.enterprise.concurrent.ManagedExecutors; import javax.enterprise.concurrent.ManagedTask; import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.core.task.TaskDecorator; import org.springframework.core.task.support.TaskExecutorAdapter; import org.springframework.lang.Nullable; import org.springframework.scheduling.SchedulingAwareRunnable; import org.springframework.scheduling.SchedulingTaskExecutor; import org.springframework.util.ClassUtils; import org.springframework.util.concurrent.ListenableFuture; /** * Adapter that takes a {@code java.util.concurrent.Executor} and exposes * a Spring {@link org.springframework.core.task.TaskExecutor} for it. * Also detects an extended {@code java.util.concurrent.ExecutorService}, adapting * the {@link org.springframework.core.task.AsyncTaskExecutor} interface accordingly. * *
Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedExecutorService} * in order to expose {@link javax.enterprise.concurrent.ManagedTask} adapters for it, * exposing a long-running hint based on {@link SchedulingAwareRunnable} and an identity * name based on the given Runnable/Callable's {@code toString()}. For JSR-236 style * lookup in a Java EE 7 environment, consider using {@link DefaultManagedTaskExecutor}. * *
Note that there is a pre-built {@link ThreadPoolTaskExecutor} that allows * for defining a {@link java.util.concurrent.ThreadPoolExecutor} in bean style, * exposing it as a Spring {@link org.springframework.core.task.TaskExecutor} directly. * This is a convenient alternative to a raw ThreadPoolExecutor definition with * a separate definition of the present adapter class. * * @author Juergen Hoeller * @since 2.0 * @see java.util.concurrent.Executor * @see java.util.concurrent.ExecutorService * @see java.util.concurrent.ThreadPoolExecutor * @see java.util.concurrent.Executors * @see DefaultManagedTaskExecutor * @see ThreadPoolTaskExecutor */ public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, SchedulingTaskExecutor { @Nullable private static Class> managedExecutorServiceClass; static { try { managedExecutorServiceClass = ClassUtils.forName( "javax.enterprise.concurrent.ManagedExecutorService", ConcurrentTaskScheduler.class.getClassLoader()); } catch (ClassNotFoundException ex) { // JSR-236 API not available... managedExecutorServiceClass = null; } } private Executor concurrentExecutor; private TaskExecutorAdapter adaptedExecutor; /** * Create a new ConcurrentTaskExecutor, using a single thread executor as default. * @see java.util.concurrent.Executors#newSingleThreadExecutor() */ public ConcurrentTaskExecutor() { this.concurrentExecutor = Executors.newSingleThreadExecutor(); this.adaptedExecutor = new TaskExecutorAdapter(this.concurrentExecutor); } /** * Create a new ConcurrentTaskExecutor, using the given {@link java.util.concurrent.Executor}. *
Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedExecutorService} * in order to expose {@link javax.enterprise.concurrent.ManagedTask} adapters for it. * @param executor the {@link java.util.concurrent.Executor} to delegate to */ public ConcurrentTaskExecutor(@Nullable Executor executor) { this.concurrentExecutor = (executor != null ? executor : Executors.newSingleThreadExecutor()); this.adaptedExecutor = getAdaptedExecutor(this.concurrentExecutor); } /** * Specify the {@link java.util.concurrent.Executor} to delegate to. *
Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedExecutorService} * in order to expose {@link javax.enterprise.concurrent.ManagedTask} adapters for it. */ public final void setConcurrentExecutor(@Nullable Executor executor) { this.concurrentExecutor = (executor != null ? executor : Executors.newSingleThreadExecutor()); this.adaptedExecutor = getAdaptedExecutor(this.concurrentExecutor); } /** * Return the {@link java.util.concurrent.Executor} that this adapter delegates to. */ public final Executor getConcurrentExecutor() { return this.concurrentExecutor; } /** * Specify a custom {@link TaskDecorator} to be applied to any {@link Runnable} * about to be executed. *
Note that such a decorator is not necessarily being applied to the * user-supplied {@code Runnable}/{@code Callable} but rather to the actual * execution callback (which may be a wrapper around the user-supplied task). *
The primary use case is to set some execution context around the task's
* invocation, or to provide some monitoring/statistics for task execution.
* @since 4.3
*/
public final void setTaskDecorator(TaskDecorator taskDecorator) {
this.adaptedExecutor.setTaskDecorator(taskDecorator);
}
@Override
public void execute(Runnable task) {
this.adaptedExecutor.execute(task);
}
@Override
public void execute(Runnable task, long startTimeout) {
this.adaptedExecutor.execute(task, startTimeout);
}
@Override
public Future> submit(Runnable task) {
return this.adaptedExecutor.submit(task);
}
@Override
public