在运行另一个Runnable之前等待Runnable完成

时间:2012-01-10 06:24:20

标签: java android

我有一个带有主标签活动的Android应用,以及各个标签内的多个活动。在我的主要活动的onCreate()中,我有一个可以创建列表的runnable,在各个活动中,我使用了这个列表。

在个人活动的onCreate()中,我还有在列表上运行的Runnables。但是,我需要这些Runnables仅在主标签活动的Runnable完成创建列表时运行,否则我将得到一个空列表。我正试图找到一种优雅的方式来做到这一点。现在,在我的主要活动的Runnable中,我正在设置一个全局布尔变量isDone,在我的个人活动的Runnable中,我正在等待isDone通过while循环设置。这可行,但可能不是最佳方式。

有什么想法吗?

感谢。

编辑: 我正在尝试以下代码,但我遇到了运行时错误:

在我的MainActivity的Runnable中:

mainRunnable = new Runnable() {
  public void run() {
    try {
      generateList();
      synchronized(this) {
      listDone = true;
      notifyAll();
    }
  } catch (Exception e) {
      Log.e("BACKGROUND_PROC", e.getMessage());
    }
  }
};
Thread thread = new Thread(null, mainRunnable, "Background");
thread.start();

在我的OtherActivity的Runnable中:

otherRunnable = new Runnable() {
  public void run() {
    synchronized(MainActivity.mainRunnable) {
      if (!MainActivity.getListDone()) {
        try {
          wait();
        } catch (InterruptedException e) {
        }
      }
    }
  }
};
Thread thread = new Thread(null, otherRunnable, "Background");
thread.start();

mainRunnable似乎完全运行,但是otherRunnable似乎导致应用程序崩溃。我收到以下错误消息:

01-10 15:41:25.543: E/WindowManager(7074): Activity com.myapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40539850 that was originally added here
01-10 15:41:25.543: E/WindowManager(7074): android.view.WindowLeaked: Activity com.myapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40539850 that was originally added here

7 个答案:

答案 0 :(得分:20)

您可以使用waitnotify方法。

要做到这一点,需要有一些全局可访问的对象,此时此程序中的任何其他内容都不会使用该锁。我假设列表创建Runnable本身可以扮演这个角色。

所以你可以在列表创建Runnable类中添加这样的东西:

private boolean listsDone = false;

boolean getListsDone() {
    return listsDone;
}

类似于run()方法,在创建列表后立即执行此操作:

synchronized (this) {
    listsDone = true;
    notifyAll();
}

对于其他Runnable s'run()方法,这类似的东西需要等待:

synchronized (listCreatingRunnableObject) {
    if (!listCreatingRunnableObject.getListsDone()) {
        try {
            listCreatingRunnableObject.wait();
        } catch (InterruptedException e) {
            // handle it somehow
        }
    }
}

更新:为了澄清,两个synchronized块需要在同一个对象上同步,您必须在该对象上调用wait()notifyAll() 。如果对象是Runnable,那么它可以隐含在第一个(如上面的代码中),但如果它是活动,则需要在两种情况下显式使用活动对象。

答案 1 :(得分:13)

您可以像这样使用Queue

public class RunQueue implemements Runnable
{
  private List<Runnable> list = new ArrayList<Runnable>();

  public void queue(Runnable task)
  {
    list.add(task);
  }

  public void run()
  {
    while(list.size() > 0)
    {
      Runnable task = list.get(0);

      list.remove(0);
      task.run();
    } 
  }
}

这允许您使用一个线程而不是多个线程。并且您可以维护所有现有的“Runnable”对象,同时清理它们用于等待和连接的任何代码。

答案 2 :(得分:9)

在主线程中设置一个值为1的CountDownLatch,然后让依赖线程等待它。完成主线程后,将锁存器倒计时为0,服务员将立即启动。

答案 3 :(得分:3)

使用while循环的主动等待根本不是一个好主意。最简单的事情就是让第一个Runnable将其余部分作为最后一步。如果由于某种原因无法使其工作,请查看向处理程序发送消息。

答案 4 :(得分:0)

是否有理由使用Runnable而不是Thread?如果您使用Thread,则可以出于这个原因使用各种线程通信原语(特别是wait()join())。

答案 5 :(得分:0)

我创建了一个帮助器方法,其中包含用于发布可运行的所有样板代码,并等待它完成运行。

逻辑类似于@Taymon所描述的,但实现更为通用。

检查出来: https://gist.github.com/Petrakeas/ce745536d8cbae0f0761

答案 6 :(得分:0)

也许您可以在Android中参考Looper。简而言之,thead可以在while循环中从队列中继续运行任务。