import org.springframework.core.task.TaskExecutor; public class TaskExecutorExample { //要执行的线程 private class MessagePrinterTask implements Runnable { private String message; public MessagePrinterTask(String message) { this.message = message; } public void run() { System.out.println(message); } } //spring 通过xml 注入的taskExecutor对象 private TaskExecutor taskExecutor; public TaskExecutorExample(TaskExecutor taskExecutor) { this.taskExecutor = taskExecutor; } public void printMessages() { for (int i = 0; i < 25; i++) { //取得线程开始执行 taskExecutor.execute(new MessagePrinterTask("Message" + i)); } } } //xml配置 <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="5"/> <property name="maxPoolSize" value="10"/> <property name="queueCapacity" value="25"/> </bean> <bean id="taskExecutorExample" class="TaskExecutorExample"> <constructor-arg ref="taskExecutor"/> </bean>
corePoolSize: 线程池维护线程的最少数量
keepAliveSeconds 线程池维护线程所允许的空闲时间
maxPoolSize 线程池维护线程的最大数量
queueCapacity 线程池所使用的缓冲队列
当一个任务通过execute(Runnable)方法欲添加到线程池时:
如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
想要spring执行@Scheduled注解要在配置文件中进行开启,@Scheduled 支持使用SpringEL表达式,这样如果我们在properties中配置好Cron值,然后注入。
@Configuration @EnableScheduling public class AppConfig { } //任务 @Component public class TestJob { @Scheduled(cron = "1 * * * * ?") public void testJob(){ System.out.println("任务1"); System.out.println(new Date().toLocaleString()); } }
如果使用xml我们可以这么写
<task:annotation-driven>
/** * The @Scheduled annotation can be added to a method along with trigger metadata. For example, * the following method would be invoked every 5 seconds with a fixed delay, * meaning that the period will be measured from the completion time of each preceding invocation. */ @Scheduled(fixedDelay=5000) public void doSomething() { // something that should execute periodically } /** * If a fixed rate execution is desired, * simply change the property name specified within the annotation. * The following would be executed every 5 seconds measured between the successive start times of each invocation. */ @Scheduled(fixedRate=5000) public void doSomething() { // something that should execute periodically } /** * For fixed-delay and fixed-rate tasks, * an initial delay may be specified indicating the number of milliseconds to wait before the first execution of the method. */ @Scheduled(initialDelay=1000, fixedRate=5000) public void doSomething() { // something that should execute periodically } /** * If simple periodic scheduling is not expressive enough, * then a cron expression may be provided. For example, * the following will only execute on weekdays. */ @Scheduled(cron="*/5 * * * * MON-FRI") public void doSomething() { // something that should execute on weekdays only }
<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass" value="example.ExampleJob" /> <property name="jobDataAsMap"> <map> <entry key="timeout" value="5" /> </map> </property> </bean> package example;public class ExampleJob extends QuartzJobBean { private int timeout; /** * Setter called after the ExampleJob is instantiated * with the value from the JobDetailBean (5) */ public void setTimeout(int timeout) { this.timeout = timeout; } protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException { // do the actual work } }
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="exampleBusinessObject" /> <property name="targetMethod" value="doIt" /> </bean> <bean id="exampleBusinessObject" class="examples.ExampleBusinessObject"/> public class ExampleBusinessObject { // properties and collaborators public void doIt() { // do the actual work } }
上面是任务实体,我们还需要触发器,下面是两种触发器
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <!-- see the example of method invoking job above --> <property name="jobDetail" ref="jobDetail" /> <!-- 10 seconds --> <property name="startDelay" value="10000" /> <!-- repeat every 50 seconds --> <property name="repeatInterval" value="50000" /> </bean> <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="exampleJob" /> <!-- run every morning at 6 AM --> <property name="cronExpression" value="0 0 6 * * ?" /> </bean>
要让定时任务允许我们还需要配置SchedulerFactoryBean
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger" /> <ref bean="simpleTrigger" /> </list> </property> </bean>