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.Executor; 020import java.util.concurrent.RejectedExecutionException; 021 022import org.apache.commons.logging.Log; 023import org.apache.commons.logging.LogFactory; 024import org.quartz.SchedulerConfigException; 025import org.quartz.spi.ThreadPool; 026 027import org.springframework.lang.Nullable; 028import org.springframework.util.Assert; 029 030/** 031 * Quartz {@link ThreadPool} adapter that delegates to a Spring-managed 032 * {@link Executor} instance, specified on {@link SchedulerFactoryBean}. 033 * 034 * @author Juergen Hoeller 035 * @since 2.0 036 * @see SchedulerFactoryBean#setTaskExecutor 037 */ 038public class LocalTaskExecutorThreadPool implements ThreadPool { 039 040 /** Logger available to subclasses. */ 041 protected final Log logger = LogFactory.getLog(getClass()); 042 043 @Nullable 044 private Executor taskExecutor; 045 046 047 @Override 048 public void setInstanceId(String schedInstId) { 049 } 050 051 @Override 052 public void setInstanceName(String schedName) { 053 } 054 055 056 @Override 057 public void initialize() throws SchedulerConfigException { 058 // Absolutely needs thread-bound Executor to initialize. 059 this.taskExecutor = SchedulerFactoryBean.getConfigTimeTaskExecutor(); 060 if (this.taskExecutor == null) { 061 throw new SchedulerConfigException("No local Executor found for configuration - " + 062 "'taskExecutor' property must be set on SchedulerFactoryBean"); 063 } 064 } 065 066 @Override 067 public void shutdown(boolean waitForJobsToComplete) { 068 } 069 070 @Override 071 public int getPoolSize() { 072 return -1; 073 } 074 075 076 @Override 077 public boolean runInThread(Runnable runnable) { 078 Assert.state(this.taskExecutor != null, "No TaskExecutor available"); 079 try { 080 this.taskExecutor.execute(runnable); 081 return true; 082 } 083 catch (RejectedExecutionException ex) { 084 logger.error("Task has been rejected by TaskExecutor", ex); 085 return false; 086 } 087 } 088 089 @Override 090 public int blockForAvailableThreads() { 091 // The present implementation always returns 1, making Quartz 092 // always schedule any tasks that it feels like scheduling. 093 // This could be made smarter for specific TaskExecutors, 094 // for example calling {@code getMaximumPoolSize() - getActiveCount()} 095 // on a {@code java.util.concurrent.ThreadPoolExecutor}. 096 return 1; 097 } 098 099}