Android?中的?Timer?和?TimerTask詳解
Timer 簡介(來自Gemini)
Timer 是 Java 中用于創(chuàng)建定時任務(wù)的類。它位于 java.util
包中??梢允褂?Timer 來安排一次性或定期執(zhí)行的任務(wù)。
每個 Timer 對象都對應(yīng)一個后臺線程。此線程負(fù)責(zé)從任務(wù)隊列中檢索任務(wù)并按計劃執(zhí)行它們。
使用 Timer
要使用 Timer,首先需要創(chuàng)建一個 Timer 對象。然后,可以使用該對象的 schedule()
方法來安排任務(wù)。
schedule()
方法有三個參數(shù):
task
: 要執(zhí)行的任務(wù)delay
: 任務(wù)延遲時間(以毫秒為單位)period
: 任務(wù)的執(zhí)行周期(以毫秒為單位)
如果 period
為 0,則任務(wù)將只執(zhí)行一次。如果 period
大于 0,則任務(wù)將定期重復(fù)執(zhí)行。
以下是一個示例,說明如何使用 Timer 來創(chuàng)建一個每隔 1 秒打印“Hello, world!”消息的任務(wù):
Timer timer = new Timer(); TimerTask task = new TimerTask() { @Override public void run() { System.out.println("Hello, world!"); } }; timer.schedule(task, 0, 1000);
Timer 和 TimerTask
TimerTask
是一個抽象類,用于表示要由 Timer 執(zhí)行的任務(wù)。TimerTask
的 run()
方法將包含要執(zhí)行的任務(wù)的代碼。
以下是一個示例 TimerTask 類,用于在 5 秒后打印“Hello, world!”消息:
class MyTimerTask extends TimerTask { @Override public void run() { System.out.println("Hello, world!"); } }
要使用 TimerTask 類,首先需要創(chuàng)建一個該類的子類。然后,可以將該子類的對象傳遞給 Timer 的 schedule()
方法。
取消 Timer 任務(wù)
可以使用 Timer 的 cancel()
方法來取消任務(wù)。
以下是一個示例,說明如何取消上例中的任務(wù):
Java
timer.cancel();
注意事項
Timer 任務(wù)是在后臺線程中執(zhí)行的。這意味著它們不應(yīng)執(zhí)行任何可能阻塞 UI 線程的操作。Timer 任務(wù)不應(yīng)該長時間運行。如果需要執(zhí)行長時間運行的任務(wù),則應(yīng)使用其他方法,例如 HandlerThread。
替代方案
除了 Timer 之外,Android 還提供了一些其他用于創(chuàng)建定時任務(wù)的類和方法。這些包括:
AlarmManager
: 用于設(shè)置一次性或定期警報Handler
: 用于在主線程或后臺線程中排隊執(zhí)行任務(wù)JobScheduler
: 用于安排在設(shè)備空閑時執(zhí)行的作業(yè)
何時使用 Timer
Timer 適用于需要在后臺執(zhí)行簡單任務(wù)的情況。例如,可以使用 Timer 來創(chuàng)建每隔幾秒刷新一次屏幕的任務(wù)或每隔幾分鐘將數(shù)據(jù)同步到服務(wù)器的任務(wù)。
但是,如果需要執(zhí)行更復(fù)雜的任務(wù)或需要確保任務(wù)在特定時間執(zhí)行,則應(yīng)使用其他方法。
Timer在cancel后不可以重復(fù)調(diào)用
在timer調(diào)用了cancel后, 再次schedule報錯:
Process: com.android.sdktest, PID: 9264 java.lang.IllegalStateException: Timer already cancelled. at java.util.Timer.sched(Timer.java:404) at java.util.Timer.schedule(Timer.java:255) at com.android.sdktester.cases.TimerTester.start(TimerTester.java:24) at com.android.sdktester.MainActivity.onClick(MainActivity.java:23) at android.view.View.performClick(View.java:7322) at android.view.View.performClickInternal(View.java:7296) at android.view.View.access$3600(View.java:839) at android.view.View$PerformClick.run(View.java:28319) at android.os.Handler.handleCallback(Handler.java:900) at android.os.Handler.dispatchMessage(Handler.java:103) at android.os.Looper.loop(Looper.java:219) at android.app.ActivityThread.main(ActivityThread.java:8673) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)
在 Android 中,Timer 類用于創(chuàng)建定時任務(wù)。Timer 的 cancel()
方法可以取消所有已安排的任務(wù)并停止 Timer 線程。一旦 Timer 線程被取消,就不能再重新啟動。
Timer 線程是一個后臺線程。當(dāng) Timer 任務(wù)被取消時,Timer 線程將被終止。這意味著 Timer 線程不再能夠執(zhí)行任何新的任務(wù)。
如果嘗試在取消 Timer 線程后重新啟動它,則會拋出 **IllegalStateException**
異常。
解決這個問題需要創(chuàng)建一個新的 Timer 對象并使用新的 schedule()
方法安排新的任務(wù)。
TimerTask 也不可以重復(fù)使用
TimerTask 類用于表示要由 Timer 執(zhí)行的任務(wù)。TimerTask 的 run()
方法將包含要執(zhí)行的任務(wù)的代碼。
原因
TimerTask 類不是線程安全的。這意味著如果同一個 TimerTask 對象被多個 Timer 任務(wù)使用,則可能導(dǎo)致數(shù)據(jù)競爭和其他問題。
Timer.java
private void sched(TimerTask task, long time, long period) { if (time < 0) throw new IllegalArgumentException("Illegal execution time."); // Constrain value of period sufficiently to prevent numeric // overflow while still being effectively infinitely large. if (Math.abs(period) > (Long.MAX_VALUE >> 1)) period >>= 1; synchronized(queue) { if (!thread.newTasksMayBeScheduled) throw new IllegalStateException("Timer already cancelled."); synchronized(task.lock) { **if (task.state != TimerTask.VIRGIN)** throw new IllegalStateException( "Task already scheduled or cancelled"); task.nextExecutionTime = time; task.period = period; task.state = TimerTask.SCHEDULED; } queue.add(task); if (queue.getMin() == task) queue.notify(); } }
TimerTask.java
public boolean cancel() { synchronized(lock) { boolean result = (state == SCHEDULED); state = CANCELLED; return result; } }
為了避免這些問題,應(yīng)為每個 Timer 任務(wù)創(chuàng)建一個新的 TimerTask 對象。
一個 Timer 可以同時計劃多個 TimerTask。
Timer 類用于創(chuàng)建定時任務(wù)。Timer 的 schedule()
方法可以安排一個或多個任務(wù)。
以下是一個示例,說明如何使用 schedule()
方法安排多個任務(wù):
Timer timer = new Timer(); TimerTask task1 = new TimerTask() { @Override public void run() { System.out.println("Task 1"); } }; TimerTask task2 = new TimerTask() { @Override public void run() { System.out.println("Task 2"); } }; timer.schedule(task1, 0, 1000); timer.schedule(task2, 500, 1000);
在這個示例中,task1
將在 0 毫秒后立即執(zhí)行,然后每隔 1 秒重復(fù)執(zhí)行一次。task2
將在 500 毫秒后執(zhí)行,然后每隔 1 秒重復(fù)執(zhí)行一次。
Timer 如何管理多個任務(wù)
Timer 使用一個隊列來存儲已安排的任務(wù)。Timer 線程負(fù)責(zé)從隊列中檢索任務(wù)并按計劃執(zhí)行它們。
當(dāng) Timer 任務(wù)被安排時,它將被添加到隊列的末尾。Timer 線程將從隊列的頭部檢索任務(wù)。這意味著最先安排的任務(wù)將首先執(zhí)行。
如果有多個任務(wù)在同一時間就緒,則 Timer 線程將按 FIFO(先進先出)的順序執(zhí)行它們。
注意事項
- Timer 任務(wù)是在后臺線程中執(zhí)行的。這意味著它們不應(yīng)執(zhí)行任何可能阻塞 UI 線程的操作。
- Timer 任務(wù)不應(yīng)該長時間運行。如果需要執(zhí)行長時間運行的任務(wù),則應(yīng)使用其他方法,例如 HandlerThread。
只要Timer不cancel, 可以反復(fù)計劃新的任務(wù)
Timer timer = new Timer(); TimerTask t1, t2, t3; //省略創(chuàng)建TimerTask代碼.... { timer.schedule(t1, 0, 1000); timer.schedule(t2, 0, 1000; Thread.sleep(10 * 1000);//等待10秒 t1.cancel(); t2.cancel(); Thread.sleep(5000); timer.schedule(t3, 0, 1000; Thread.sleep(5000); t3.cancel(); } timer.cancel()
這段代碼使用了 Thread.sleep()
方法來控制任務(wù)的執(zhí)行順序。在 Thread.sleep()
方法執(zhí)行期間,Timer 線程無法從任務(wù)隊列中檢索任務(wù),因此即使 t1
和 t2
任務(wù)已經(jīng)被取消,它們也不會再被執(zhí)行。使用了 t1.cancel()
和 t2.cancel()
方法來顯式地將 t1
和 t2
任務(wù)從 Timer 的任務(wù)隊列中刪除。這可以確保這兩個任務(wù)不會再次被執(zhí)行.
參考
Android 開發(fā)Timer與TimerTask - 觀心靜
到此這篇關(guān)于Android 的 Timer 和 TimerTask的文章就介紹到這了,更多相關(guān)Android Timer 和 TimerTask內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android編程開發(fā)之Spinner控件用法實例分析
這篇文章主要介紹了Android編程開發(fā)之Spinner控件用法,結(jié)合實例形式較為詳細(xì)的分析了下拉列表Spinner的具體使用技巧,需要的朋友可以參考下2015-12-12Android定制RadioButton樣式三種實現(xiàn)方法
三種方法實現(xiàn)Android定制RadioButton樣式:使用XML文件進行定義/在JAVA代碼中定義等等,感興趣的朋友可以參考下,希望可以幫助到你2013-02-02Android實戰(zhàn)教程第七篇之如何在內(nèi)存中存儲用戶名和密碼
這篇文章主要為大家詳細(xì)介紹了Android如何實現(xiàn)在內(nèi)存中存儲用戶名和密碼的相關(guān)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-11-11Android 幾種屏幕間跳轉(zhuǎn)的跳轉(zhuǎn)Intent Bundle
這篇文章主要介紹了Android 幾種屏幕間跳轉(zhuǎn)的跳轉(zhuǎn)Intent Bundle,有需要的朋友可以參考一下2013-12-12android使用Ultra-PullToRefresh實現(xiàn)下拉刷新自定義代碼
本篇文章主要介紹了android使用Ultra-PullToRefresh實現(xiàn)下拉刷新新自定義,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-02-02