1、Timer管理延时任务的缺陷
a、以前在项目中也经常使用定时器,比如每隔一段时间清理项目中的一些垃圾文件,每个一段时间进行数据清洗;然而Timer是存在一些缺陷的,因为Timer在执行定时任务时只会创建一个线程,所以如果存在多个任务,且任务时间过长,超过了两个任务的间隔时间,会发生一些缺陷:下面看例子:
Timer的源码:
public class Timer { /** * The timer task queue. This data structure is shared with the timer * thread. The timer produces tasks, via its various schedule calls, * and the timer thread consumes, executing timer tasks as appropriate, * and removing them from the queue when they're obsolete. */ private TaskQueue queue = new TaskQueue(); /** * The timer thread. */ private TimerThread thread = new TimerThread(queue);
TimerThread是Thread的子类,可以看出内部只有一个线程。下面看个例子:
package com.zhy.concurrency.timer; import java.util.Timer; import java.util.TimerTask; public class TimerTest { private static long start; public static void main(String[] args) throws Exception { TimerTask task1 = new TimerTask() { @Override public void run() { System.out.println("task1 invoked ! " + (System.currentTimeMillis() - start)); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } }; TimerTask task2 = new TimerTask() { @Override public void run() { System.out.println("task2 invoked ! " + (System.currentTimeMillis() - start)); } }; Timer timer = new Timer(); start = System.currentTimeMillis(); timer.schedule(task1, 1000); timer.schedule(task2, 3000); } }
定义了两个任务,预计是第一个任务1s后执行,第二个任务3s后执行,但是看运行结果:
task1 invoked ! 1000 task2 invoked ! 4000
task2实际上是4后才执行,正因为Timer内部是一个线程,而任务1所需的时间超过了两个任务间的间隔导致。下面使用ScheduledThreadPool解决这个问题:
package com.zhy.concurrency.timer; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class ScheduledThreadPoolExecutorTest { private static long start; public static void main(String[] args) { /** * 使用工厂方法初始化一个ScheduledThreadPool */ ScheduledExecutorService newScheduledThreadPool = Executors .newScheduledThreadPool(2); TimerTask task1 = new TimerTask() { @Override public void run() { try { System.out.println("task1 invoked ! " + (System.currentTimeMillis() - start)); Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); } } }; TimerTask task2 = new TimerTask() { @Override public void run() { System.out.println("task2 invoked ! " + (System.currentTimeMillis() - start)); } }; start = System.currentTimeMillis(); newScheduledThreadPool.schedule(task1, 1000, TimeUnit.MILLISECONDS); newScheduledThreadPool.schedule(task2, 3000, TimeUnit.MILLISECONDS); } }
输出结果:
task1 invoked ! 1001 task2 invoked ! 3001
符合我们的预期结果。因为ScheduledThreadPool内部是个线程池,所以可以支持多个任务并发执行。
2、Timer当任务抛出异常时的缺陷
如果TimerTask抛出RuntimeException,Timer会停止所有任务的运行:
package com.zhy.concurrency.timer; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class ScheduledThreadPoolDemo01 { public static void main(String[] args) throws InterruptedException { final TimerTask task1 = new TimerTask() { @Override public void run() { throw new RuntimeException(); } }; final TimerTask task2 = new TimerTask() { @Override public void run() { System.out.println("task2 invoked!"); } }; Timer timer = new Timer(); timer.schedule(task1, 100); timer.scheduleAtFixedRate(task2, new Date(), 1000); } }
上面有两个任务,任务1抛出一个运行时的异常,任务2周期性的执行某个操作,输出结果:
task2 invoked! Exception in thread "Timer-0" java.lang.RuntimeException at com.zhy.concurrency.timer.ScheduledThreadPoolDemo01$1.run(ScheduledThreadPoolDemo01.java:24) at java.util.TimerThread.mainLoop(Timer.java:512) at java.util.TimerThread.run(Timer.java:462)
由于任务1的一次,任务2也停止运行了。。。下面使用ScheduledExecutorService解决这个问题:
package com.zhy.concurrency.timer; import java.util.Date; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class ScheduledThreadPoolDemo01 { public static void main(String[] args) throws InterruptedException { final TimerTask task1 = new TimerTask() { @Override public void run() { throw new RuntimeException(); } }; final TimerTask task2 = new TimerTask() { @Override public void run() { System.out.println("task2 invoked!"); } }; ScheduledExecutorService pool = Executors.newScheduledThreadPool(1); pool.schedule(task1, 100, TimeUnit.MILLISECONDS); pool.scheduleAtFixedRate(task2, 0 , 1000, TimeUnit.MILLISECONDS); } }
代码基本一致,但是ScheduledExecutorService可以保证,task1出现异常时,不影响task2的运行:
task2 invoked! task2 invoked! task2 invoked! task2 invoked! task2 invoked!<span style="font-family: Arial, Helvetica, sans-serif;">...</span>
3、Timer执行周期任务时依赖系统时间
Timer执行周期任务时依赖系统时间,如果当前系统时间发生变化会出现一些执行上的变化,ScheduledExecutorService基于时间的延迟,不会由于系统时间的改变发生执行变化。
上述,基本说明了在以后的开发中尽可能使用ScheduledExecutorService(JDK1.5以后)替代Timer。
以上是Java用ScheduledExecutorService取代Timer的程式碼實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JVMmanagesgarbagecollectionacrossplatformseffectivelybyusingagenerationalapproachandadaptingtoOSandhardwaredifferences.ItemploysvariouscollectorslikeSerial,Parallel,CMS,andG1,eachsuitedfordifferentscenarios.Performancecanbetunedwithflagslike-XX:NewRa

Java代碼可以在不同操作系統上無需修改即可運行,這是因為Java的“一次編寫,到處運行”哲學,由Java虛擬機(JVM)實現。 JVM作為編譯後的Java字節碼與操作系統之間的中介,將字節碼翻譯成特定機器指令,確保程序在任何安裝了JVM的平台上都能獨立運行。

Java程序的編譯和執行通過字節碼和JVM實現平台獨立性。 1)編寫Java源碼並編譯成字節碼。 2)使用JVM在任何平台上執行字節碼,確保代碼的跨平台運行。

Java性能与硬件架构密切相关,理解这种关系可以显著提升编程能力。1)JVM通过JIT编译将Java字节码转换为机器指令,受CPU架构影响。2)内存管理和垃圾回收受RAM和内存总线速度影响。3)缓存和分支预测优化Java代码执行。4)多线程和并行处理在多核系统上提升性能。

使用原生庫會破壞Java的平台獨立性,因為這些庫需要為每個操作系統單獨編譯。 1)原生庫通過JNI與Java交互,提供Java無法直接實現的功能。 2)使用原生庫增加了項目複雜性,需要為不同平台管理庫文件。 3)雖然原生庫能提高性能,但應謹慎使用並進行跨平台測試。

JVM通過JavaNativeInterface(JNI)和Java標準庫處理操作系統API差異:1.JNI允許Java代碼調用本地代碼,直接與操作系統API交互。 2.Java標準庫提供統一API,內部映射到不同操作系統API,確保代碼跨平台運行。

modularitydoesnotdirectlyaffectJava'splatformindependence.Java'splatformindependenceismaintainedbytheJVM,butmodularityinfluencesapplicationstructureandmanagement,indirectlyimpactingplatformindependence.1)Deploymentanddistributionbecomemoreefficientwi

BytecodeinJavaistheintermediaterepresentationthatenablesplatformindependence.1)Javacodeiscompiledintobytecodestoredin.classfiles.2)TheJVMinterpretsorcompilesthisbytecodeintomachinecodeatruntime,allowingthesamebytecodetorunonanydevicewithaJVM,thusfulf


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

WebStorm Mac版
好用的JavaScript開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

禪工作室 13.0.1
強大的PHP整合開發環境