java实现周期任务_java定时任务的实现方式
本文列舉常見的java定時(shí)任務(wù)實(shí)現(xiàn)方式,并做一定比較。
1. 循環(huán)內(nèi)部sleep實(shí)現(xiàn)周期執(zhí)行
創(chuàng)建一個(gè)thread,run() while循環(huán)里sleep()來實(shí)現(xiàn)周期性執(zhí)行; 簡(jiǎn)單粗暴,作為一個(gè)初學(xué)者很容易想到。
public class Task1 {
public static void main(String[] args) {
// run in a second
final long timeInterval = 1000;
Runnable runnable = new Runnable() {
public void run() {
while (true) {
System.out.println("Hello !!");
// 使用線程休眠來實(shí)現(xiàn)周期執(zhí)行,
try {
Thread.sleep(timeInterval);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
2. 使用Timer類調(diào)度TimerTask任務(wù)
改進(jìn):當(dāng)啟動(dòng)和去取消任務(wù)時(shí)可以控制; 第一次執(zhí)行任務(wù)時(shí)可以指定你想要的delay時(shí)間
不足:
Timer的調(diào)度是基于絕對(duì)時(shí)間的,所以當(dāng)系統(tǒng)時(shí)間改變時(shí)會(huì)影響Timer。
Timer只有一個(gè)工作線程,所以當(dāng)一個(gè)任務(wù)執(zhí)行時(shí)間很長(zhǎng)的時(shí)候,會(huì)影響后續(xù)任務(wù)的調(diào)度。
而ScheduledThreadPoolExecutor通過線程池的方式配置更靈活。
如果任務(wù)拋出了一個(gè)未檢查的異常,將會(huì)導(dǎo)致Timer的工作線程被終止,使Timer無法在繼續(xù)運(yùn)行。
import java.util.Timer;
import java.util.TimerTask;
public class HelperTest {
public static void main(String[] args) {
// 具體任務(wù)。
TimerTask task = new TimerTask() {
@Override
public void run() {
// task to run goes here
System.out.println("Hello !!!");
}
};
// Timer類可以調(diào)度任務(wù)。 Timer實(shí)例可以調(diào)度多任務(wù),它是線程安全的。
Timer timer = new Timer();
long delay = 0;
long intevalPeriod = 1 * 1000;
// schedules the task to be run in an interval
timer.scheduleAtFixedRate(task, delay, intevalPeriod);
}
}
3. 使用j.u.c.ScheduledExecutorService定時(shí)任務(wù)接口
相比于Timer的單線程,它是通過線程池的方式來執(zhí)行任務(wù)的
可以靈活的設(shè)定第一次執(zhí)行任務(wù)delay時(shí)間
提供了良好的約定,以便設(shè)定執(zhí)行的時(shí)間間隔
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Task3 {
public static void main(String[] args) {
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1);
// 初始化延遲0ms開始執(zhí)行,每隔200ms重新執(zhí)行一次任務(wù)。
ScheduledExecutorService pool = new ScheduledThreadPoolExecutor(1);
pool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// task to run goes here
System.out.println("Hello !");
}
}, 0, 200L, TimeUnit.MILLISECONDS);
}
實(shí)現(xiàn)類使用的是ScheduledThreadPoolExecutor。該類繼承自ThreadPoolExecutor read more,阻塞隊(duì)列使用的是DelayedWorkQueue,是ScheduledThreadPoolExecutor的內(nèi)部類。
ScheduledExecutorService接口方法說明:
其中scheduleAtFixedRate和scheduleWithFixedDelay在實(shí)現(xiàn)定時(shí)程序時(shí)比較方便。
scheduleAtFixedRate(runnable, 0, 200L, TimeUnit.MILLISECONDS) 按指定周期執(zhí)行某個(gè)任務(wù)
初始化延遲0ms開始執(zhí)行,每隔200ms重新執(zhí)行一次任務(wù)。
scheduleWithFixedDelay(runnable, 0, 200L, TimeUnit.MILLISECONDS) 按指定間隔執(zhí)行某個(gè)任務(wù)
初始化時(shí)延時(shí)0ms開始執(zhí)行,下次執(zhí)行時(shí)間是(本次執(zhí)行結(jié)束 + 延遲200ms)后開始執(zhí)行。
schedule(Runnable command, long delay, TimeUnit unit) 在delay延時(shí)后執(zhí)行一次性任務(wù)
備注:對(duì)于scheduleAtFixedRate,實(shí)際上如果當(dāng)前線程阻塞執(zhí)行時(shí)間t > 設(shè)置的間隔時(shí)間period,下次是在t時(shí)間后執(zhí)行,并非period時(shí)間后立即開始。
ScheduledExecutorService的spring配置
>> spring.xml
>> xxx.java
@Autowired
@Qualifier("gkHeartBeatScheduler")
ScheduledExecutorService scheduledExecutorService;
scheduledExecutorService.scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
System.out.println("do sth");
}
}, 1l, 2l, TimeUnit.SECONDS);
spring ScheduledExecutorFactoryBean內(nèi)部同樣使用的ScheduledThreadPoolExecutor,并對(duì)其做了包裝處理。
public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport implements FactoryBean
4. @Sheduled注解方式
@Sheduled內(nèi)部也使用了ScheduledThreadPoolExecutor。具體源代碼可參見:spring-context包中的ScheduledAnnotationBeanPostProcessor。
用法就很簡(jiǎn)單了,舉例:
pom文件引入spring-context依賴
使用注解方式配置定時(shí)任務(wù)即可
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@EnableScheduling
public class ScheduledAnnotationDemo {
// @Scheduled和觸發(fā)器元素一起添加到方法上.
@Scheduled(fixedDelay=5000)
public void doSomething() {
System.out.println("like scheduleWithFixedDelay");
}
@Scheduled(fixedRate=5000)
public void doSomething() {
System.out.println("like scheduleAtFixedRate");
}
// fixed-delay、fixed-rate任務(wù)都可以設(shè)置初始delay。
@Scheduled(initialDelay=1000, fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
// 也支持cron表達(dá)式
@Scheduled(cron = "0/5 * * * * ?")
public void doSomething() {
// something that should execute on weekdays only
System.out.println("5s執(zhí)行一次");
}
//cron舉例:(秒 - 分 - 時(shí) - 日 - 月- 星期)
// */5 * * * * ? 每隔5秒執(zhí)行一次
// 0 */1 * * * ? 每隔1分鐘執(zhí)行一次
// 0 0 1 * * ? 每天1點(diǎn)執(zhí)行一次
// 0 0 1 1 * ? 每月1號(hào)1點(diǎn)執(zhí)行一次
// 0 0 1 L * ? 每月最后一天1點(diǎn)執(zhí)行一次
// 0 0 1 ? * L 每周星期天1點(diǎn)執(zhí)行一次
}
上面使用@EnableScheduling的方式啟動(dòng)定時(shí)任務(wù),等價(jià)于在spring xml中配置元素。
5. 開源任務(wù)調(diào)度框架Quartz
Quartz , 功能強(qiáng)大的任務(wù)調(diào)度庫。適用于具有更復(fù)雜調(diào)度要求的場(chǎng)景。
提供了對(duì)持久化任務(wù)調(diào)度信息、事務(wù)、分布式的支持。與spring無縫對(duì)接。
6. 小結(jié)
使用ScheduledThreadPoolExecutor完成簡(jiǎn)單定時(shí)任務(wù),是比較理想和常用的實(shí)現(xiàn)方式。書寫時(shí)更容易理解其過程實(shí)現(xiàn)。
也可以用@Sheduled注解的形式,更加輕量化,看起來更簡(jiǎn)潔。
對(duì)復(fù)雜的任務(wù)調(diào)度,可以使用Quartz框架。
總結(jié)
以上是生活随笔為你收集整理的java实现周期任务_java定时任务的实现方式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 异常管理员_GitHub -
- 下一篇: 做男性不育检需到上饶哪家医院好