断电断点
作者:互联网
Spring Framework分别通过TaskExecutor和TaskScheduler两个接口提供了异步执行任务和定时任务的功能。Spring还实现了这两个接口支持线程池和委派给CommonJ在服务器环境下。最终,这些实现区分了Java SE 5、Java SE 6和Java EE环境。
Spring还整合支持Timer和Quartz Scheduler。你可以通过使用FactoryBean来分别的实例化Timer和Trigger实例。而且,还有一个简便的类用于Quartz Scheduler和Timer让你在一个存在的的对象中异步调用方法。(类似于MethodInvokingFactoryBean的操作)
#### Spring TaskExecutor 抽象
执行是JDK为线程池的概念,名称“executor”事实上无法保证实际工作的是线程池。一个“executor”可能是单线程也可能是同步的,Spring的抽象层隐藏了在Java SE和Java EE环境下实现的不同。
Spring的TaskExecutor跟java.util.concurrent.Executor接口是雷同的。事实上,当在Java5中使用线程池的时候,需要抽象出来,是它存在的主要原因。接口中仅仅包含了一个execute方法用来接口基于语法和配置的线程池。
TaskExecutor为其他Spring组件抽象出来的线程池需要的地方使用。比如ApplicationEventMulticaster和JMS的AbstractMessageListenerContainer和Quart整合的TaskExecutor抽象线程池。但是,如果你的类需要线程池功能,你依然可以为你自己使用这个抽象层
---
##### TaskExecutor 类型
Spring包含了一些实现TaskExecutor前置类,在所有的情况,你应该是不要自己来实现这些接口的,下面是Spring提供的几种类型:
* SyncTaskExecutor:这个实现类,不会异步执行调用。相反,每次调用都会在调用线程中进行,这个主要适用于非多线程的环境,比如简单的测试用例中。
* SimpleAsyncTaskExecutor:这个实现类,不会重用任何其他线程,宁可为每次的调用起一个新的线程。而且,它还支持多线程限制,在限制的线程中阻止其他的调用。如果你在寻找真正意义长的线程池,可以查看ThreadPoolTaskExecutor,就在稍后的列表中。
* ConcurrentTaskExecutor:这个是为java.util.concurrent.Executor实例的一个适配类。这是个可选的,相当于把Executor的配置参数作为这个的类属性。很少有情况需要直接使用ConcurrentTaskExecutor。然后,如果TreadPoolTaskExecutor灵活度不满足你的需求,ConcurrentTaskExecutor是一个不错的选择。
* ThreadPoolTaskExecutor:这个实现类是最长被使用到的。它为java.util.concurrent.ThreadPoolExecutor提供配置类属性并封装在TaskExecutor中。如果你需要适配一个不同类型的java.util.concurrent.Executor,我们推荐你使用ConcurrentTaskExecutor。
* WorkManagerTaskExecutor:这个类的实现使用了CommonJ的WorkManager作为它的支持服务。并且,在Spring应用上下文中,它是实现了基于CommonJ线程池集WebLogic或者WebSphere方式的最简单方法。
* DefaultManagedTaskExecutor:这个实现使用了JNDI-obtained ManagedExecutorService在JSR-236适配的环境中,为了替换CommonJ WorkManager。
---
##### 使用一个TaskExecutor
Spring的TaskExecutor实现作为一个简单的Java类使用,在下面的实例中,我们定义了一个使用了ThreadPoolTaskExecutor用于异步输出信息的类。
```java
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);
}
}
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));
}
}
}
```
正如你所看到的,你添加了线程到队列中,而不是从线程池中接口一个线程,然后自行执行。TaskExecutor使用内部规则来决定任何合适被执行。
配置TaskExecutor的使用规则,如下我们展示了简单的类属性配置:
```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>
```
---
#### Spring TaskScheduler抽象层
除了TaskExecutor抽象层,Spring 3.0引用了TaskScheduler类,它携带了大量的方法,可以设置在未来的某个时间点运行。下面列表展示了TaskScheduler接口定义:
```java
public interface TaskScheduler {
ScheduledFuture schedule(Runnable task, Trigger trigger);
ScheduledFuture schedule(Runnable task, Instant startTime);
ScheduledFuture schedule(Runnable task, Date startTime);
ScheduledFuture scheduleAtFixedRate(Runnable task, Instant startTime, Duration period);
ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period);
ScheduledFuture scheduleAtFixedRate(Runnable task, Duration period);
ScheduledFuture scheduleAtFixedRate(Runnable task, long period);
ScheduledFuture scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay);
ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
ScheduledFuture scheduleWithFixedDelay(Runnable task, Duration delay);
ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);
}
```
其中最简单的方式是一个名为shcedule的方法,它仅仅只需要一个线程和一个时间。这种会在时间到的之后,执行一次任务。其他所有的方法都是可以进行重复任务协作的。固定的周期和延时用于简单的周期执行,但是接受触发器的方式更为灵活。
##### Trigger接口
Trigger接口实际上是受JSR-236的启发,在Spring3.0中还未正式的被实现。使用Trigger的基本方法是执行次数受限于过去的执行结果或者任意条件。如果确实考虑了前面的执行结果,那么这些信息在TriggerContext中就可以使用。Trigger的接口非常简单,如下列表所示:
```java
public interface Trigger {
Date nextExecutionTime(TriggerContext triggerContext);
}
```
TriggerContext是最重要的部分,它包含了所有的相关数据,如果有需要还可以对它进行扩展。TriggerContext是一个接口,SimpleTriggerContext被作为默认的实现。下面列出了Trigger实现的相关可用方法:
```java
public interface TriggerContext {
Date lastScheduledExecutionTime();
Date lastActualExecutionTime();
Date lastCompletionTime();
}
```
##### Trigger实现
Spring提供了Trigger接口的两个实现。最有趣的是CronTrigger类,它允许任务安全基于闹钟表达式。举个例子,下列任务呗安排在工作日上午9点到5点,每个小时后的15分钟后执行。
```java
scheduler.schedule(task, new CronTrigger("0 15 9-17 * * MON-FRI"));
```
另一个实现是PeriodicTrigger,它接收固定周期、一个初始化的延迟时间和一个布尔值来确定执行周期被解读为固定率还是固定延时。因为TaskScheduler接口已经为固定比例和固定延时来分配任务,这些方法我们应该尽可能的直接调用。PerioddicTrigger实现可以基于Trigger抽象层来使用。比如,在使用周期出发、基于时钟出发和自定义出发实现上达到互换的能力是很方便的。这样的组件可以非常方便的配置和使用。
##### TaskScheduler实现
作为Spring中的TaskExecutor抽象层,首要的好处是TaskScheduler任务安排和开发应用环境解耦。当部署的应用服务器,线程不由应用本身直接创建的时候,这个抽象层显得额外的重要。在这种场景,Spring提供了TimerManagerTaskScheduler整合CommonJ的TimerManager在WebLogic和WebSphere上也是可以的
标签:task,Spring,Trigger,断电,Runnable,线程,TaskExecutor,断点 来源: https://www.cnblogs.com/deky97/p/10975040.html