3

Object.wait(timeout)在我的android应用服务中使用过。但它不计算在“深度睡眠模式”中花费的时间。我使用 AlarmManager 定期唤醒我的应用程序,因此从深度睡眠中醒来不是问题。问题是wait(60000)在 100 秒的深度睡眠后不会终止。

正如我在SystemClock帮助页面上阅读的那样,object.wait使用uptimeMillis()方法,该方法在深度睡眠中停止计数。对于我的需要,使用elapsedRealtime()会更好。

我如何实现类似Object.wait(timeout)但使用elapsedRealtime方法?或者我可以用什么代替?


我使用此方法的任务之一是在一段时间内没有其他数据包在队列中时生成“ping”数据包以通过网络发送。

4

3 回答 3

1

您提到(在评论中)interrupt()导致终止(杀死)线程,虽然这是完全错误的,但它只是向等待/加入/睡眠线程抛出异常。

public void Foo implements Runnable{
  public void run(){
   //do some work
   try{Thread.sleep(10000);}catch(Exception ex){/*when thread got interrupted*/}
   //do something else
  }
}

问题就在这里,因为你把所有的业务都放在了一个try块中,所以中断会导致代码跳转到catch之后没有任何业务的块中,所以这不是线程的事情。

于 2013-10-25T10:09:47.870 回答
1

而不是使用普通的 Object.wait() 或 Thread.sleep() 我建议您使用以下任何一种:

  1. 使用 java.util.concurrent.newScheduledThreadPool 它使您能够以固定间隔或延迟安排任务。使用 threadCount = 1 初始化线程池会为您提供一个线程。

  2. 使用允许您安排 TimerTask 的 java.util.Timer。

我认为 1. 是一种首选方法。

如果您有特定要求要插入计时器对象或使用特定或第 3 方计时提供程序,您需要做的是编写自己的调度程序来包装 ScheduledExecutorService,然后使用您自己的计时器转换时间或从您自己的计时器中获取时间。基本上,您使用自己的时间计算在包装服务上启动计划任务。

我的演员模型中有一个这样的调度程序示例,如下所示。看看这个包中的 DefaultScheduler。它可能有点错误(我还没有完全测试过),但它应该给你一个好主意。

http://sourceforge.net/p/jalgo/code-0/HEAD/tree/trunk/src/org/as/algo/threading/

于 2013-10-28T03:29:22.000 回答
0

不确定它是否完全符合您的要求,但我写这篇文章是为了暂停一段时间,但让其他线程过早唤醒我。

它在BlockingQueue内部使用 a 来做它的睡眠,因此它避免使用sleepwait所有伴随它们而来的悲伤。

不确定它在 Android 下会如何运作,我不使用它,但我怀疑你现有的AlarmManager工作会适应。

/**
 * Use one of these to doze for a certain time.
 *
 * The dozing is fully interruptable.
 *
 * Another thread can stop the caller's doze with either a wakeup call or an abort call.
 *
 * These can be interpreted in any way you like but it is intended that a Wakeup is
 * interpreted as a normal awakening and should probably be treated in exactly the
 * same way as an Alarm. An Abort should probably be interpreted as a suggestion
 * to abandon the process.
 */
public class Doze {
  // Special alarm messages.
  public enum Alarm {
    // Standard timeout.
    Alarm,
    // Forced wake from your doze.
    Wakeup,
    // Abort the whole Doze process.
    Abort;
  }
  // My queue to wait on.
  private final BlockingQueue<Alarm> doze = new ArrayBlockingQueue<>(1);
  // How long to wait by default.
  private final long wait;

  public Doze(long wait) {
    this.wait = wait;
  }

  public Doze() {
    this(0);
  }

  public Alarm doze() throws InterruptedException {
    // Wait that long.
    return doze(wait);
  }

  public Alarm doze(long wait) throws InterruptedException {
    // Wait that long.
    Alarm poll = doze.poll(wait, TimeUnit.MILLISECONDS);
    // If we got nothing then it must be a normal wakeup.
    return poll == null ? Alarm.Alarm : poll;
  }

  public void wakeup() {
    // Just post a Wakeup.
    doze.add(Alarm.Wakeup);
  }

  public void abort() {
    // Signal the system to abort.
    doze.add(Alarm.Abort);
  }

  private static long elapsed ( long start ) {
    return System.currentTimeMillis() - start;
  }

  // Test code.
  public static void main(String[] args) throws InterruptedException {
    // Doze for 1 second at a time.
    final Doze d = new Doze(1 * 1000);
    final long start = System.currentTimeMillis();

    // Start a dozing thread.
    new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          Alarm a = d.doze();
          // Wait forever until we are aborted.
          while (a != Alarm.Abort) {
            System.out.println(elapsed(start) + ": Doze returned " + a);
            a = d.doze();
          }
          System.out.println(elapsed(start) + ": Doze returned " + a);
        } catch (InterruptedException ex) {
          // Just exit on interrupt.
        }
      }

    }).start();


    // Wait for a few seconds.
    Thread.sleep(3210);

    // Wake it up.
    d.wakeup();

    // Wait for a few seconds.
    Thread.sleep(4321);

    // Abort it.
    d.abort();


  }

}
于 2013-10-30T09:19:58.050 回答