介绍java 定时任务最简单的3种实现方法
java基础教程介绍定时任务在实际的开发
推荐(免费):java基础教程
日子匆匆穿过我而行,奔向海洋。
定时任务在实际的开发中特别常见,比如电商平台 30 分钟后自动取消未支付的订单,以及凌晨的数据汇总和备份等,都需要借助定时任务来实现,那么我们本文就来看一下定时任务最简单的几种实现方式。
TOP 1:Timer
Timer 是 JDK 自带的定时任务执行类,无论任何项目都可以直接使用 Timer 来实现定时任务,所以 Timer 的优点就是使用方便,它的实现代码如下:
public class MyTimerTask { public static void main(String[] args) { // 定义一个任务 TimerTask timerTask = new TimerTask() { @Override public void run() { System.out.println("Run timerTask:" + new Date()); } }; // 计时器 Timer timer = new Timer(); // 添加执行任务(延迟 1s 执行,每 3s 执行一次) timer.schedule(timerTask, 1000, 3000); } }
程序执行结果如下:
Run timerTask:Mon Aug 17 21:29:25 CST 2020 Run timerTask:Mon Aug 17 21:29:28 CST 2020 Run timerTask:Mon Aug 17 21:29:31 CST 2020
Timer 缺点分析
Timer 类实现定时任务虽然方便,但在使用时需要注意以下问题。
问题 1:任务执行时间长影响其他任务
当一个任务的执行时间过长时,会影响其他任务的调度,如下代码所示:
public class MyTimerTask { public static void main(String[] args) { // 定义任务 1 TimerTask timerTask = new TimerTask() { @Override public void run() { System.out.println("进入 timerTask 1:" + new Date()); try { // 休眠 5 秒 TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Run timerTask 1:" + new Date()); } }; // 定义任务 2 TimerTask timerTask2 = new TimerTask() { @Override public void run() { System.out.println("Run timerTask 2:" + new Date()); } }; // 计时器 Timer timer = new Timer(); // 添加执行任务(延迟 1s 执行,每 3s 执行一次) timer.schedule(timerTask, 1000, 3000); timer.schedule(timerTask2, 1000, 3000); } }
程序执行结果如下:
进入 timerTask 1:Mon Aug 17 21:44:08 CST 2020 Run timerTask 1:Mon Aug 17 21:44:13 CST 2020 Run timerTask 2:Mon Aug 17 21:44:13 CST 2020 进入 timerTask 1:Mon Aug 17 21:44:13 CST 2020 Run timerTask 1:Mon Aug 17 21:44:18 CST 2020 进入 timerTask 1:Mon Aug 17 21:44:18 CST 2020 Run timerTask 1:Mon Aug 17 21:44:23 CST 2020 Run timerTask 2:Mon Aug 17 21:44:23 CST 2020 进入 timerTask 1:Mon Aug 17 21:44:23 CST 2020
从上述结果中可以看出,当任务 1 运行时间超过设定的间隔时间时,任务 2 也会延迟执行。 原本任务 1 和任务 2 的执行时间间隔都是 3s,但因为任务 1 执行了 5s,因此任务 2 的执行时间间隔也变成了 10s(和原定时间不符)。
问题 2:任务异常影响其他任务
使用 Timer 类实现定时任务时,当一个任务抛出异常,其他任务也会终止运行,如下代码所示:
public class MyTimerTask { public static void main(String[] args) { // 定义任务 1 TimerTask timerTask = new TimerTask() { @Override public void run() { System.out.println("进入 timerTask 1:" + new Date()); // 模拟异常 int num = 8 / 0; System.out.println("Run timerTask 1:" + new Date()); } }; // 定义任务 2 TimerTask timerTask2 = new TimerTask() { @Override public void run() { System.out.println("Run timerTask 2:" + new Date()); } }; // 计时器 Timer timer = new Timer(); // 添加执行任务(延迟 1s 执行,每 3s 执行一次) timer.schedule(timerTask, 1000, 3000); timer.schedule(timerTask2, 1000, 3000); } }
程序执行结果如下:
进入 timerTask 1:Mon Aug 17 22:02:37 CST 2020 Exception in thread "Timer-0" java.lang.ArithmeticException: / by zero at com.example.MyTimerTask$1.run(MyTimerTask.java:21) at java.util.TimerThread.mainLoop(Timer.java:555) at java.util.TimerThread.run(Timer.java:505) Process finished with exit code 0
Timer 小结
Timer 类实现定时任务的优点是方便,因为它是 JDK 自定的定时任务,但缺点是任务如果执行时间太长或者是任务执行异常,会影响其他任务调度,所以在生产环境下建议谨慎使用。
TOP 2:ScheduledExecutorService
ScheduledExecutorService 也是 JDK 1.5 自带的 API,我们可以使用它来实现定时任务的功能,也就是说 ScheduledExecutorService 可以实现 Timer 类具备的所有功能,并且它可以解决了 Timer 类存在的所有问题。
ScheduledExecutorService 实现定时任务的代码示例如下:
public class MyScheduledExecutorService { public static void main(String[] args) { // 创建任务队列 ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); // 10 为线程数量 // 执行任务 scheduledExecutorService.scheduleAtFixedRate(() -> { System.out.println("Run Schedule:" + new Date()); }, 1, 3, TimeUnit.SECONDS); // 1s 后开始执行,每 3s 执行一次 } }
程序执行结果如下:
Run Schedule:Mon Aug 17 21:44:23 CST 2020 Run Schedule:Mon Aug 17 21:44:26 CST 2020 Run Schedule:Mon Aug 17 21:44:29 CST 2020
ScheduledExecutorService 可靠性测试
① 任务超时执行测试
ScheduledExecutorService 可以解决 Timer 任务之间相应影响的缺点,首先我们来测试一个任务执行时间过长,会不会对其他任务造成影响,测试代码如下:
public class MyScheduledExecutorService { public static void main(String[] args) { // 创建任务队列 ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); // 执行任务 1 scheduledExecutorService.scheduleAtFixedRate(() -> { System.out.println("进入 Schedule:" + new Date()); try { // 休眠 5 秒 TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Run Schedule:" + new Date()); }, 1, 3, TimeUnit.SECONDS); // 1s 后开始执行,每 3s 执行一次 // 执行任务 2 scheduledExecutorService.scheduleAtFixedRate(() -> { System.out.println("Run Schedule2:" + new Date()); }, 1, 3, TimeUnit.SECONDS); // 1s 后开始执行,每 3s 执行一次 } }
程序执行结果如下:
Run Schedule2:Mon Aug 17 11:27:55 CST 2020 进入 Schedule:Mon Aug 17 11:27:55 CST 2020 Run Schedule2:Mon Aug 17 11:27:58 CST 2020 Run Schedule:Mon Aug 17 11:28:00 CST 2020 进入 Schedule:Mon Aug 17 11:28:00 CST 2020 Run Schedule2:Mon Aug 17 11:28:01 CST 2020 Run Schedule2:Mon Aug 17 11:28:04 CST 2020
从上述结果可以看出,当任务 1 执行时间 5s 超过了执行频率 3s 时,并没有影响任务 2 的正常执行,因此使用 ScheduledExecutorService 可以避免任务执行时间过长对其他任务造成的影响。
② 任务异常测试
接下来我们来测试一下 ScheduledExecutorService 在一个任务异常时,是否会对其他任务造成影响,测试代码如下:
public class MyScheduledExecutorService { public static void main(String[] args) { // 创建任务队列 ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); // 执行任务 1 scheduledExecutorService.scheduleAtFixedRate(() -> { System.out.println("进入 Schedule:" + new Date()); // 模拟异常 int num = 8 / 0; System.out.println("Run Schedule:" + new Date()); }, 1, 3, TimeUnit.SECONDS); // 1s 后开始执行,每 3s 执行一次 // 执行任务 2 scheduledExecutorService.scheduleAtFixedRate(() -> { System.out.println("Run Schedule2:" + new Date()); }, 1, 3, TimeUnit.SECONDS); // 1s 后开始执行,每 3s 执行一次 } }
程序执行结果如下:
进入 Schedule:Mon Aug 17 22:17:37 CST 2020 Run Schedule2:Mon Aug 17 22:17:37 CST 2020 Run Schedule2:Mon Aug 17 22:17:40 CST 2020 Run Schedule2:Mon Aug 17 22:17:43 CST 2020
从上述结果可以看出,当任务 1 出现异常时,并不会影响任务 2 的执行。
ScheduledExecutorService 小结
在单机生产环境下建议使用 ScheduledExecutorService 来执行定时任务,它是 JDK 1.5 之后自带的 API,因此使用起来也比较方便,并且使用 ScheduledExecutorService 来执行任务,不会造成任务间的相互影响。
TOP 3:Spring Task
如果使用的是 Spring 或 Spring Boot 框架,可以直接使用 Spring Framework 自带的定时任务,使用上面两种定时任务的实现方式,很难实现设定了具体时间的定时任务,比如当我们需要每周五来执行某项任务时,但如果使用 Spring Task 就可轻松的实现此需求。
以 Spring Boot 为例,实现定时任务只需两步:
- 开启定时任务;
- 添加定时任务。
具体实现步骤如下。
① 开启定时任务
开启定时任务只需要在 Spring Boot 的启动类上声明 @EnableScheduling
即可,实现代码如下:
@SpringBootApplication @EnableScheduling // 开启定时任务 public class DemoApplication { // do someing }
② 添加定时任务
定时任务的添加只需要使用 @Scheduled
注解标注即可,如果有多个定时任务可以创建多个 @Scheduled
注解标注的方法,示例代码如下:
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component // 把此类托管给 Spring,不能省略 public class TaskUtils { // 添加定时任务 @Scheduled(cron = "59 59 23 0 0 5") // cron 表达式,每周五 23:59:59 执行 public void doTask(){ System.out.println("我是定时任务~"); } }
注意:定时任务是自动触发的无需手动干预,也就是说 Spring Boot 启动后会自动加载并执行定时任务。
Cron 表达式
Spring Task 的实现需要使用 cron 表达式来声明执行的频率和规则,cron 表达式是由 6 位或者 7 位组成的(最后一位可以省略),每位之间以空格分隔,每位从左到右代表的含义如下:
其中 * 和 ? 号都表示匹配所有的时间。
cron 表达式在线生成地址:https://cron.qqe2.com/
Atas ialah kandungan terperinci 介绍java 定时任务最简单的3种实现方法. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Adeadlockinjaoccurswhentwoormorethreadsareblockedforever, eachwaitingforaresourceHeldByTheother, biasanyaduetoculularwaitcausedbyinconsistentlockordering;

UseOptional.empty (), optional.of (), andOptional.ofnullable () tOcreateOptionalInStancesDependingOnwhethetheValueisabsent, non-null, orpossiblynull.2.CheckForvalUessafelySpresent () orprefeAdoShoDoD.

Memahami komponen teras JCA seperti MessageDigest, Cipher, KeyGenerator, SecureRandom, Signature, Keystore, dan lain -lain, yang melaksanakan algoritma melalui mekanisme penyedia; 2. Gunakan algoritma dan parameter yang kuat seperti SHA-256/SHA-512, AES (Kunci 256-bit, mod GCM), RSA (2048-bit atau ke atas) dan SecureRandom; 3. Elakkan kunci berkod keras, gunakan KeyStore untuk menguruskan kunci, dan menjana kunci melalui kata laluan yang diperoleh dengan selamat seperti PBKDF2; 4. Lumpuhkan mod ECB, mengamalkan mod penyulitan pengesahan seperti GCM, menggunakan IV rawak yang unik untuk setiap penyulitan, dan yang sensitif yang jelas pada waktunya

Inti springdatajpa dan hibernate yang bekerja bersama adalah: 1. JPA adalah spesifikasi dan hibernate adalah pelaksanaan, SpringDatajpa enkapsulasi memudahkan pembangunan DAO; 2. Kelas entiti Peta pangkalan data pangkalan data melalui @Entity, @id, @column, dan sebagainya; 3. Antara muka repositori mewarisi JParepository untuk melaksanakan kaedah pertanyaan CRUD dan dinamakan secara automatik; 4. Pertanyaan Kompleks Gunakan @Query Anotation untuk menyokong JPQL atau SQL asli; 5. Dalam springboot, integrasi disiapkan dengan menambah kebergantungan starter dan mengkonfigurasi sumber data dan atribut JPA; 6. Urus niaga dibuat oleh @transactiona

Kelas corak digunakan untuk menyusun ungkapan biasa, dan kelas Matcher digunakan untuk melakukan operasi yang sepadan pada rentetan. Gabungan kedua -duanya dapat merealisasikan carian teks, padanan dan penggantian; Mula -mula buat objek corak melalui corak.comPile (), dan kemudian panggil kaedah pencocokannya () untuk menghasilkan contoh yang sepadan. Kemudian gunakan perlawanan () untuk menilai pemadanan rentetan penuh, cari () untuk mencari berikutnya, menggantikan () atau penggantiFirst () untuk penggantian. Jika biasa mengandungi kumpulan penangkapan, kandungan kumpulan nth boleh diperolehi melalui kumpulan (n). Dalam aplikasi sebenar, anda harus mengelakkan corak penyusunan berulang, memberi perhatian kepada watak khas yang melarikan diri, dan menggunakan bendera corak yang sepadan seperti yang diperlukan, dan akhirnya mencapai cekap

Penyuntingan penanda buku Chrome adalah mudah dan praktikal. Pengguna boleh memasukkan pengurus penanda buku melalui kekunci pintasan CTRL Shift O (Windows) atau CMD Shift O (MAC), atau masuk melalui menu penyemak imbas; 1. Apabila menyunting penanda buku tunggal, klik kanan untuk memilih "Edit", ubah suai tajuk atau URL dan klik "Selesai" untuk menyimpan; 2. Apabila menganjurkan penanda buku dalam kelompok, anda boleh memegang Ctrl (atau CMD) kepada penanda buku pelbagai pilihan dalam pengurus penanda buku, klik kanan untuk memilih "Pindah ke" atau "Salin ke" folder Sasaran; 3. Apabila mengeksport dan mengimport penanda halaman, klik butang "Solve" untuk memilih "penanda buku eksport" untuk menyimpan sebagai fail HTML, dan kemudian pulihkannya melalui fungsi "Import Bookmark" jika perlu.
![Tetapan permainan lol tidak menyimpan selepas ditutup [tetap]](https://img.php.cn/upload/article/001/431/639/175597664176545.jpg?x-oss-process=image/resize,m_fill,h_207,w_330)
Ifleagueoflegendssettingsaren'tsaving, trythesesteps: 1.runthegameasadministrator.2.grantfullfolderpermissionstotheleagueof LegendsDirectory.3.Editandensuregame.cfgisn'tread-only.4.disableCloudsyncforthegamefolder.5.RepairthegameviAveAveAtheriotClient.

Pilihan adalah kelas kontena yang diperkenalkan oleh Java 8. Ia digunakan dengan jelas menunjukkan bahawa nilai mungkin kosong, dengan itu mengelakkan NullPointerException; 2. Ia memudahkan pemeriksaan null bersarang dengan menyediakan peta, orelse dan kaedah lain, mencegah kaedah dari mengembalikan nilai pulangan dan penyeragaman pengumpulan; 3. Amalan terbaik termasuk hanya nilai yang kembali, mengelakkan penggunaan medan atau parameter, membezakan Orelse dari Orelseget, dan tidak memanggil GET () secara langsung; 4. Pilihan tidak boleh disalahgunakan. Sekiranya kaedah yang tidak kosong tidak perlu dibungkus, operasi pilihan yang tidak perlu harus dielakkan dalam aliran; Penggunaan yang betul pilihan boleh meningkatkan keselamatan kod dan kebolehbacaan, tetapi ia memerlukan tabiat pengaturcaraan yang baik.
