幾種常見的延遲執行處理方式

懶懶初陽發表於2023-03-26

Android中常見的延遲執行方法有哪些,各有什麼優缺點。應用場景是什麼

在 Android 中,常見的延遲執行方法有以下幾種:

  1. Handler.postDelayed():在指定的時間後向 Handler 傳送一個延遲執行的訊息,透過 Handler 的 handleMessage() 方法來執行。

優點:簡單易用,可以在主執行緒中進行延遲操作。

缺點:只能在主執行緒中使用,如果需要在子執行緒中延遲執行,則需要透過 Handler.post() 方法來實現。

應用場景:需要在主執行緒中延遲執行一些操作,如延遲更新 UI 介面。

示例程式碼:

java

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        // 延遲執行的操作
    }
}, 1000); // 延遲 1 秒鐘執行
  1. Timer.schedule():使用 Timer 物件來實現延遲執行,可以指定延遲時間和執行週期。

優點:可以在任何執行緒中使用,支援週期性執行任務。

缺點:Timer 物件是單執行緒的,如果有多個任務需要執行,則需要建立多個 Timer 物件。

應用場景:需要在子執行緒中延遲執行一些任務,如定時任務、週期性任務等。

示例程式碼:

java

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        // 延遲執行的操作
    }
}, 1000); // 延遲 1 秒鐘執行
  1. Executors.newScheduledThreadPool().schedule():使用 ScheduledExecutorService 物件來實現延遲執行,可以指定延遲時間和執行週期。

優點:可以在任何執行緒中使用,支援週期性執行任務,可以控制執行緒池的大小。

缺點:相對於 Timer 物件,使用 ScheduledExecutorService 物件需要更多的程式碼。

應用場景:需要在子執行緒中延遲執行一些任務,如定時任務、週期性任務等。

示例程式碼:

java

ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.schedule(new Runnable() {
    @Override
    public void run() {
        // 延遲執行的操作
    }
}, 1000, TimeUnit.MILLISECONDS); // 延遲 1 秒鐘執行

選擇延遲執行方法需要根據具體的應用場景來決定。如果需要在主執行緒中延遲執行操作,則可以使用 Handler.postDelayed() 方法;如果需要在子執行緒中延遲執行、週期性操作,則可以使用 Timer.schedule() 或 Executors.newScheduledThreadPool().schedule() 方法。

用handlerthread獲取的looper。不需要進行額外的looper.prepare 和 loop啟動

使用 HandlerThread 獲取的 Looper 已經經過了初始化和啟動,不需要再進行額外的 Looper.prepare() 和 Looper.loop() 操作。

HandlerThread 是一個帶有 Looper 的執行緒類,它繼承自 Thread,並實現了建立 Looper 的功能。透過 HandlerThread,可以在子執行緒中建立 Handler,並使用 Handler.postDelayed() 方法來實現延遲任務。使用 HandlerThread 可以省略掉建立 Looper、初始化和啟動 Looper 的步驟,使得程式碼更加簡潔。

下面是一個使用 HandlerThread 來實現延遲任務的示例程式碼:

java

HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();

Handler handler = new Handler(handlerThread.getLooper()) {
    @Override
    public void handleMessage(Message msg) {
        // 延遲執行的操作
    }
};

handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        // 延遲執行的操作
    }
}, 1000); // 延遲 1 秒鐘執行

需要注意的是,使用 HandlerThread 來執行延遲任務時,需要確保執行緒不會在延遲時間內被銷燬。如果執行緒被銷燬,那麼 Handler.postDelayed() 方法也將失效,延遲任務將無法執行。

android中哪些延時任務可以取消的

在Android中,可以取消的延時任務主要有以下幾種:

  1. 使用Handler.postDelayed()方法傳送的延時訊息可以透過呼叫Handler.removeCallbacks()方法來取消。

  2. 使用CountDownTimer進行倒數計時的任務可以透過呼叫CountDownTimer.cancel()方法來取消。

  3. 使用ScheduledExecutorService.schedule()方法排程的延時任務可以透過呼叫ScheduledFuture.cancel()方法來取消。

  4. 使用Timer.schedule()方法排程的延時任務可以透過呼叫TimerTask.cancel()方法來取消。

需要注意的是,對於已經執行的延時任務無法取消,只能取消尚未執行的任務。另外,如果需要取消延時任務,建議在任務執行前儘早進行取消操作,避免出現不必要的效能浪費和資源佔用。

上面的場景給出具體的實現

以下是對上述場景的具體實現:

  1. 使用Handler.postDelayed()方法傳送的延時訊息可以透過呼叫Handler.removeCallbacks()方法來取消。

java

// 建立Handler物件
Handler handler = new Handler();
// 傳送延時訊息
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        // 執行任務
    }
}, delayTime);
// 取消延時任務
handler.removeCallbacksAndMessages(null);
  1. 使用CountDownTimer進行倒數計時的任務可以透過呼叫CountDownTimer.cancel()方法來取消。

java

// 建立CountDownTimer物件
CountDownTimer countDownTimer = new CountDownTimer(countDownTime, intervalTime) {
    @Override
    public void onTick(long millisUntilFinished) {
        // 倒數計時執行中
    }

    @Override
    public void onFinish() {
        // 倒數計時執行完成
    }
};
// 開始倒數計時
countDownTimer.start();
// 取消倒數計時
countDownTimer.cancel();
  1. 使用ScheduledExecutorService.schedule()方法排程的延時任務可以透過呼叫ScheduledFuture.cancel()方法來取消。

java

// 建立ScheduledExecutorService物件
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
// 排程延時任務
ScheduledFuture<?> scheduledFuture = scheduledExecutorService.schedule(new Runnable() {
    @Override
    public void run() {
        // 執行任務
    }
}, delayTime, TimeUnit.MILLISECONDS);
// 取消延時任務
scheduledFuture.cancel(true);
  1. 使用Timer.schedule()方法排程的延時任務可以透過呼叫TimerTask.cancel()方法來取消。

java

// 建立Timer物件
Timer timer = new Timer();
// 排程延時任務
TimerTask timerTask = new TimerTask() {
    @Override
    public void run() {
        // 執行任務
    }
};
timer.schedule(timerTask, delayTime);
// 取消延時任務
timerTask.cancel();

幾種常見的延遲執行處理方式

  1. 分執行緒增加sleep;
    1. try {
    2. Thread.sleep(5000); // 睡眠5秒鐘
    3. } catch (InterruptedException e) {
    4. e.printStackTrace();
    5. }
  2. TimerTask、timer.schedule
    1. TimerTask task = new TimerTask() {
    2. @Override
    3. public void run() {
    4. // 執行你需要延遲執行的任務
    5. }
    6. };
    7. new Timer().schedule(task, 5000); // 延遲5秒鐘執行
  3. ScheduledExecutorService來延遲執行
    1. ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    2. executor.schedule(() -> {
    3. // 執行你需要延遲執行的任務
    4. }, 5000, TimeUnit.MILLISECONDS); // 延遲5秒鐘執行

Executors.newScheduledThreadPool、Handler.postDelayed()和Timer都可以延遲執行一個執行緒或任務,但是它們有著不同的優點和缺點。

  • Executors.newScheduledThreadPool
    優點:
    * 能夠實現相比 Timer 更加強大的定時排程功能,並且因為多執行緒處理,可以減少因為某個任務耗時導致下一個任務被延遲而產生的誤差。
    * 執行緒池中執行緒的數量可以按照需要進行調整。
    * 對於頻繁地、反覆地執行同一任務來說,執行緒池機制比非執行緒池機制具有更高的效率。
    缺點:
    * 需要了解多執行緒的知識,並對執行緒池的實現原理及其建構函式引數有一定理解。
    * 對於只執行一次並延遲時間較長的任務,也許直接使用 Thread.sleep 就能夠達到要求,但是定時執行緒池卻沒有那麼方便和直觀。
    希望能回答您的問題,如還有不理解的可以繼續提問。
    * Runnable task = new Runnable() {
    * @Override
    * public void run() {
    * System.out.println("Hello World!");
    * }
    * };
    *
    * ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
    *
    * // 延遲 5 秒執行
    * executor.schedule(task, 5, TimeUnit.SECONDS);
    *
    * // 關閉執行緒池
    * executor.shutdown();
  • Handler.postDelayed()
優點:它很方便使用, 並且在一些特殊場景下使用它更加方便(例如需要延遲的執行緒需要與UI互動等)。
缺點:它本質上是在UI執行緒上行動的一個排程任務,所以如果任務細微地超出了預期的時間間隔,則會對使用者體驗產生負面影響。
  • Timer
優點:它是Java語言自帶的物件, JVM都支援它,易於使用。
缺點:它容易發生各種拋異常錯誤,並且不能跨程式使用。

相關文章