【问题标题】:Interrrupt-able ScheduledExecutorService in AndroidAndroid中的中断表ScheduledExecutorService
【发布时间】:2017-02-28 06:24:55
【问题描述】:

目前,我正在设计一个具有以下要求的股票市场应用程序

  • 1) 反复扫描股价,固定休眠时间。
  • 2) 可以随时中断睡眠。这是因为当用户添加新股票时,我们需要从睡眠中醒来,并立即扫描。

以前,我使用裸骨Thread 来完全满足上述两个要求。

private class StockMonitor extends Thread { 
    @Override
    public void run() {
        final Thread thisThread = Thread.currentThread();

        while (thisThread == thread) {

            // Fetch stock prices...

            try {
                Thread.sleep(MIN_DELAY);
            } catch (java.lang.InterruptedException exp) {
                if (false == refreshed()) {
                    /* Exit the primary fail safe loop. */
                    thread = null;                            
                    break;
                }
            }
        }
    }

    public synchronized void refresh() {        
        isRefresh = true;
        interrupt();
    }

    private synchronized boolean refreshed() {
        if (isRefresh) {
            isRefresh = false;
            // Interrupted status of the thread is cleared.
            interrupted();
            return true;
        }
        return false;
    }
}

当我想执行要求(2)时,我会打电话给refresh。线程将被唤醒,并立即执行作业。

但是,我觉得这种裸露的 Thread 代码很难维护,而且很容易出错。

我更喜欢使用ScheduledExecutorService。但是,我无法将线程从睡眠状态中唤醒并立即执行工作。

我想知道,Android 中是否有任何类可以让我定期执行ScheduledExecutorService 中的任务?却有能力将线程从休眠状态唤醒,并立即执行工作。

【问题讨论】:

    标签: java android multithreading


    【解决方案1】:

    这是我使用ScheduledThreadPoolExecutor 的解决方案。要取消现有任务,请在从 scheduleAtFixedRate() 返回的 Future 对象上发出 future.cancel()。然后再次调用scheduleAtFixedRate() 并将initial delay 设置为0。

    class HiTask implements Runnable {
        @Override
        public void run() {
            System.out.println("Say Hi!");
        } 
    }
    
    // periodically execute task in every 100 ms, without initial delay time
    
    ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
    
    long initialDelay = 0;
    long period = 100;
    
    ScheduledFuture<?> future1 = exec.scheduleAtFixedRate(new HiTask(), initialDelay, period, TimeUnit.MILLISECONDS);
    
    
    // to trigger task execution immediately
    
    boolean success = future.cancel(true);    // mayInterruptIfRunning = true: interrupt thread even task has already started
    
    ScheduledFuture<?> future2 = exec.scheduleAtFixedRate(new HiTask(), initialDelay, period, TimeUnit.MILLISECONDS);
    

    【讨论】:

      【解决方案2】:

      ScheduledExecutorService 的选项:

      • submit() 在您需要刷新数据的那一刻再次执行相同的任务。 If 将立即执行(并且仅执行一次)。可能的缺点:如果这发生在非常接近计划执行的时间,您将进行两次扫描,中间的时间很短。
      • cancel() 需要刷新数据时的任务,submit() 立即执行一次,schedule() 重复执行。

      请注意,任务中发生的任何未处理的异常都会取消未来的执行。 How to reschedule a task using a ScheduledExecutorService?回答了如何解决。

      ExecutorService 不是持久的(即无法在设备重新启动后继续存在)。我不知道这对你来说是不是一个问题。如果有专门用于 Android 上的后台任务执行的库:

      您必须应用上述相同的解决方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-09
        • 1970-01-01
        • 2015-08-19
        • 2014-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-05
        相关资源
        最近更新 更多