001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.scheduling.quartz; 018 019import java.util.concurrent.Callable; 020import java.util.concurrent.Future; 021import java.util.concurrent.FutureTask; 022 023import org.quartz.SchedulerConfigException; 024import org.quartz.simpl.SimpleThreadPool; 025 026import org.springframework.beans.factory.DisposableBean; 027import org.springframework.beans.factory.InitializingBean; 028import org.springframework.core.task.AsyncListenableTaskExecutor; 029import org.springframework.scheduling.SchedulingException; 030import org.springframework.scheduling.SchedulingTaskExecutor; 031import org.springframework.util.Assert; 032import org.springframework.util.concurrent.ListenableFuture; 033import org.springframework.util.concurrent.ListenableFutureTask; 034 035/** 036 * Subclass of Quartz's SimpleThreadPool that implements Spring's 037 * {@link org.springframework.core.task.TaskExecutor} interface 038 * and listens to Spring lifecycle callbacks. 039 * 040 * <p>Can be shared between a Quartz Scheduler (specified as "taskExecutor") 041 * and other TaskExecutor users, or even used completely independent of 042 * a Quartz Scheduler (as plain TaskExecutor backend). 043 * 044 * @author Juergen Hoeller 045 * @since 2.0 046 * @see org.quartz.simpl.SimpleThreadPool 047 * @see org.springframework.core.task.TaskExecutor 048 * @see SchedulerFactoryBean#setTaskExecutor 049 */ 050public class SimpleThreadPoolTaskExecutor extends SimpleThreadPool 051 implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, InitializingBean, DisposableBean { 052 053 private boolean waitForJobsToCompleteOnShutdown = false; 054 055 056 /** 057 * Set whether to wait for running jobs to complete on shutdown. 058 * Default is "false". 059 * @see org.quartz.simpl.SimpleThreadPool#shutdown(boolean) 060 */ 061 public void setWaitForJobsToCompleteOnShutdown(boolean waitForJobsToCompleteOnShutdown) { 062 this.waitForJobsToCompleteOnShutdown = waitForJobsToCompleteOnShutdown; 063 } 064 065 @Override 066 public void afterPropertiesSet() throws SchedulerConfigException { 067 initialize(); 068 } 069 070 071 @Override 072 public void execute(Runnable task) { 073 Assert.notNull(task, "Runnable must not be null"); 074 if (!runInThread(task)) { 075 throw new SchedulingException("Quartz SimpleThreadPool already shut down"); 076 } 077 } 078 079 @Override 080 public void execute(Runnable task, long startTimeout) { 081 execute(task); 082 } 083 084 @Override 085 public Future<?> submit(Runnable task) { 086 FutureTask<Object> future = new FutureTask<>(task, null); 087 execute(future); 088 return future; 089 } 090 091 @Override 092 public <T> Future<T> submit(Callable<T> task) { 093 FutureTask<T> future = new FutureTask<>(task); 094 execute(future); 095 return future; 096 } 097 098 @Override 099 public ListenableFuture<?> submitListenable(Runnable task) { 100 ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null); 101 execute(future); 102 return future; 103 } 104 105 @Override 106 public <T> ListenableFuture<T> submitListenable(Callable<T> task) { 107 ListenableFutureTask<T> future = new ListenableFutureTask<>(task); 108 execute(future); 109 return future; 110 } 111 112 113 @Override 114 public void destroy() { 115 shutdown(this.waitForJobsToCompleteOnShutdown); 116 } 117 118}