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)該長時間運(yùn)行。如果需要執(zhí)行長時間運(yùn)行的任務(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(先進(jìn)先出)的順序執(zhí)行它們。
注意事項
- Timer 任務(wù)是在后臺線程中執(zhí)行的。這意味著它們不應(yīng)執(zhí)行任何可能阻塞 UI 線程的操作。
- Timer 任務(wù)不應(yīng)該長時間運(yùn)行。如果需要執(zhí)行長時間運(yùn)行的任務(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控件用法實(shí)例分析
這篇文章主要介紹了Android編程開發(fā)之Spinner控件用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了下拉列表Spinner的具體使用技巧,需要的朋友可以參考下2015-12-12
Android動畫學(xué)習(xí)筆記之補(bǔ)間動畫
這篇文章主要為大家詳細(xì)介紹了Android動畫學(xué)習(xí)筆記之補(bǔ)間動畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-12-12
Android定制RadioButton樣式三種實(shí)現(xiàn)方法
三種方法實(shí)現(xiàn)Android定制RadioButton樣式:使用XML文件進(jìn)行定義/在JAVA代碼中定義等等,感興趣的朋友可以參考下,希望可以幫助到你2013-02-02
Android實(shí)戰(zhàn)教程第七篇之如何在內(nèi)存中存儲用戶名和密碼
這篇文章主要為大家詳細(xì)介紹了Android如何實(shí)現(xiàn)在內(nèi)存中存儲用戶名和密碼的相關(guān)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-11-11
Android中自定義對話框(Dialog)的實(shí)例代碼
這篇文章介紹了Android中自定義對話框(Dialog)的實(shí)例代碼,有需要的朋友可以參考一下2013-08-08
Android 幾種屏幕間跳轉(zhuǎn)的跳轉(zhuǎn)Intent Bundle
這篇文章主要介紹了Android 幾種屏幕間跳轉(zhuǎn)的跳轉(zhuǎn)Intent Bundle,有需要的朋友可以參考一下2013-12-12
android使用Ultra-PullToRefresh實(shí)現(xiàn)下拉刷新自定義代碼
本篇文章主要介紹了android使用Ultra-PullToRefresh實(shí)現(xiàn)下拉刷新新自定義,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-02-02

