javascript
oracle trigger 延迟执行_一文详解Spring任务执行和调度
一、概述
Spring框架分別使用TaskExecutor和TaskScheduler接口提供異步執行和任務調度的抽象。Spring還提供了這些接口的實現,這些接口支持線程池或將其委托給應用服務器環境中的CommonJ。
二、TaskExecutor
Spring 2.0 開始引入的新的抽像。Executors 是線程池的Java 5名稱。之所以稱作是“執行器”是因為不能保證底層實現實際上是一個池;執行程序可以是單線程的,甚至是同步的。Spring的TaskExecutor接口與java.util.concurrent是等價的。
2.1 TaskExecutor類型
SimpleAsyncTaskExecutor
線程不會重用,每次調用開啟一個新的線程。支持并發,超過最大并發調用數時,會阻塞,直到釋放一個槽為止。
SyncTaskExecutor
不會異步執行調用。每次調用都發生在調用線程中。它主要用于不需要多線程的情況。
ConcurrentTaskExecutor
Java 5 Java .util.concurrent. executor的包裝。替代方案是ThreadPoolTaskExecutor,它將Executor配置參數作為bean屬性公開。很少使用。
SimpleThreadPoolTaskExecutor
Quartz的SimpleThreadPool的一個子類,它監聽Spring的生命周期回調。Quartz組件和非Quartz組件共享需要共享一個線程池時,通常會使用這種方法。
ThreadPoolTaskExecutor
只能在java5中使用。公開了用于配置java.util.concurrent的bean屬性。如果需要高級的東西,比如ScheduledThreadPoolExecutor,建議使用ConcurrentTaskExecutor替代。
TimerTaskExecutor
通過TimerTask支撐實現。 不同于SyncTaskExecutor,因為方法調用在一個單獨的線程中執行,盡管它們在那個線程中是同步的。
WorkManagerTaskExecutor
使用CommonJ WorkManager作為它的支持實現,并且是在Spring上下文中設置CommonJ WorkManager引用的中心便利類。與SimpleThreadPoolTaskExecutor類似,這個類實現了WorkManager接口,因此也可以直接作為WorkManager使用。
2.2 使用 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)); } }}與其從池中檢索線程并自己執行,不如將Runnable添加到隊列中,而TaskExecutor使用其內部規則來決定任務何時執行
配置TaskExecutor將使用的規則
三、TaskScheduler
除了任務執行者抽象之外。Spring 3.0還引入了一個TaskScheduler,它有多種方法來調度未來某個時候運行的任務。
public interface TaskScheduler { ScheduledFuture schedule(Runnable task, Trigger trigger); ScheduledFuture schedule(Runnable task, Date startTime); ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period); ScheduledFuture scheduleAtFixedRate(Runnable task, long period); ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay); ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);}名為“schedule”的方法,它只接受可運行的日期。這將導致任務在指定時間后運行一次。
所有其他方法都能夠安排任務重復運行。固定速率和固定延遲方法用于簡單的、周期性的執行,但是使用 Trigger 的方法要靈活得多。
3.1 Trigger
觸發器的基本思想是,執行時間可以根據過去的執行結果甚至任意條件來確定。如果這些決定確實考慮了前面執行的結果,那么該信息在TriggerContext中是可用的。
public interface Trigger { Date nextExecutionTime(TriggerContext triggerContext);}public interface TriggerContext { Date lastScheduledExecutionTime(); Date lastActualExecutionTime(); Date lastCompletionTime();}TriggerContext是最重要的部分。它封裝了所有相關的數據,如果有必要,將來還可以進行擴展。TriggerContext是一個接口(默認情況下使用SimpleTriggerContext實現)。
3.2 Trigger 實現
Spring提供了觸發器接口的兩個實現。最有趣的是CronTrigger。它支持基于cron表達式的任務調度。
scheduler.schedule(task, new CronTrigger("* 15 9-17 * * MON-FRI"));
另一個開箱即用的實現是一個周期性Trigger ,它接受一個固定的周期、一個可選的初始延遲值,以及一個布爾值,用來指示周期應該解釋為固定速率還是固定延遲。由于TaskScheduler接口已經定義了以固定速率或固定延遲調度任務的方法,因此應該盡可能直接使用這些方法。PeriodicTrigger實現的價值在于它可以在依賴于觸發器抽象的組件中使用。例如,允許周期性Trigger 、基于cro的Trigger ,甚至自定義Trigger 實現可以互換使用,這可能很方便。這樣的組件可以利用依賴注入,這樣就可以在外部配置這樣的Trigger 。
3.3 TaskScheduler實現
在應用服務器環境中,TaskScheduler提供的靈活性尤其重要。因為在這種環境中,線程不應該由應用程序本身直接創建。對于這種情況,Spring提供了一個TimerManagerTaskScheduler,它將委托給CommonJ TimerManager實例,通常配置為JNDI-lookup。
四、調度和異步執行的注解支持
4.1 開啟scheduling 注解功能
為了支持@Scheduled和@Async注釋,請將@EnableScheduling和@EnableAsync添加到@Configuration類中
@Configuration@EnableAsync@EnableSChedulingpublic class AppConfig {}你可以自由選擇應用程序的相關注釋。例如,如果只需要支持@Scheduled,那么只需省略@EnableAsync即可。對于更細粒度的控制,可以另外實現調度器和/或AsyncConfigurer接口。
如果你更喜歡xml配置,這樣配置。
}4.2 @Scheduled
@Scheduled添加到方法上
//上一次調用完之后,五秒再調用一次,依此循環下去@Scheduled(fixedDelay=5000)public void doSomething() { // something that should execute periodically}//連續的每次調用開始時間之間,間隔5s@Scheduled(fixedRate=5000)public void doSomething() { // something that should execute periodically}//@Scheduled(cron="*/5 * * * * MON-FRI")public void doSomething() { // something that should execute on weekdays only}值得注意的是調度的方法返回值必須是void,并且不能期望有任何參數。如果方法需要與來自應用程序上下文的其他對象交互,那么這些對象通常是通過依賴注入提供的。
4.3 @Async注解
添加了@Async注解的方法會異步執行。換句話說,方法調用后會立即返回,方法的實際執行將發生在提交給Spring TaskExecutor的任務中。
@Asyncvoid doSomething() { // this will be executed asynchronously}/@Scheduled注釋的方法不同,這些方法可以預期參數.//因為調用方將在運行時以“正常”方式調用它們,而不是從容器管理的調度任務中調用。@Asyncvoid doSomething(String s) { // this will be executed asynchronously}// 具有Future回調返回值//執行其它任務的優先級 依然是高于執行回調的優先級。@AsyncFuture returnSomething(int i) { // this will be executed asynchronously}4.4 指定@Async注解的執行器
默認情況下,在方法上指定@Async時,將使用的執行器是提供“annotation-driven”元素的執行器,如上所述。然而,當需要指示在執行給定方法時應該使用非默認的執行器時,可以使用@Async注釋的值屬性。
@Async("otherExecutor")void doSomething(String s) { // this will be executed asynchronously by "otherExecutor"}五、Task 命名空間
從Spring 3.0開始,有一個用于配置TaskExecutor和TaskScheduler實例的XML名稱空間。并提供了一種方便的方法,可以將任務配置為使用觸發器進行調度。
5.1 scheduler 元素
id屬性用作線程池中線程的前綴名。如果不指定pool-size,默認的線程池中只有一個線程。
5.2 executor元素
與上面的調度器一樣,為’id’屬性提供的值將用作池中線程名稱的前綴。就池大小而言,'executor’元素比’scheduler’元素支持更多的配置選項。首先,ThreadPoolTaskExecutor的線程池本身是可配置的。執行程序的線程池可能對核心和最大大小有不同的值,而不僅僅是單個大小。如果提供了單個值,那么執行器將擁有一個固定大小的線程池(核心和最大大小相同)。然而,“executor”元素的“池大小”屬性也接受“min-max”形式的范圍。
5.3 scheduled-tasks元素
Spring task namespace 最強大的特性是支持在Spring應用程序上下文中配置要調度的任務。這與Spring中的其他“方法調用者”類似,例如JMS名稱空間提供的配置消息驅動pojo的方法。
六、Quartz Scheduler
Quartz使用觸發器、作業和作業細節對象來實現各種作業的調度。有關Quartz背后的基本概念,請參閱http://quartz-scheduling er.org。為了方便起見,Spring提供了兩個類,它們簡化了基于Spring的應用程序中Quartz的使用。
6.1 使用JobDetailBean
JobDetail對象包含運行作業所需的所有信息。Spring框架提供了JobDetailBean,它使JobDetail更接近于具有合理默認值的實際JavaBean。
job detail bean 具有運行作業(ExampleJob)所需的所有信息。timeout在job data map指定。job data map可以通過JobExecutionContext(在執行時傳遞給您)獲得,但是JobDetailBean還將 job data map 中的屬性映射到實際job的屬性。因此,在本例中,如果ExampleJob包含一個名為timeout的屬性,JobDetailBean將自動應用它。
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 }}6.2 使用MethodInvokingJobDetailFactoryBean
使用MethodInvokingJobDetailFactoryBean你可以調用特定對象上的方法。
使用上面的配置將會導致ExampleBusinessObject .doIt()方法被調用。
public class ExampleBusinessObject { // properties and collaborators public void doIt() { // do the actual work }}使用MethodInvokingJobDetailFactoryBean,不再需要創建只調用一個方法的一行作業,只需要創建實際的業務對象并連接到它。
默認情況下,Quartz作業是無狀態的,導致作業相互干擾的可能性。如果為相同的JobDetail指定兩個觸發器,那么可能在第一個作業完成之前,第二個作業就會開始。如果JobDetail類實現有狀態接口,則不會發生這種情況。在第一項工作完成之前,第二項工作不會開始。要使方法調用jobdetailfactorybean產生的作業非并發,請將并發標志設置為false。
6.3 作業調度
盡管我們能使用MethodInvokingJobDetailFactoryBean調用特定對象上的方法,但是我們還是需要調度作業 。這需要使用觸發器和scheduler erfactorybean完成。Quartz 提供了多種觸發器
Spring提供了兩種Quartz 工廠對象:
- CronTriggerFactoryBean
- SimpleTriggerFactoryBean
兩種觸發器的示例
關于SchedulerFactoryBean的等多屬性設置 ,參考SchedulerFactoryBean javadoc
Java架構師丨蘇先生:專注于Java開發技術的研究與知識分享!
————END————
- 點贊(感謝)
- ...
- 轉發(感謝)
- ...
- 關注(感謝)
- ...
推薦閱讀
Java程序員備戰“金九銀十”必備的面試技巧(附攜程Java崗面試題)
字節跳動Java研發面試99題(含答案):JVM+Spring+MySQL+線程池+鎖
......
總結
以上是生活随笔為你收集整理的oracle trigger 延迟执行_一文详解Spring任务执行和调度的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle怎么修改表字段长度,Orac
- 下一篇: iftables 官方文档