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

问题描述 投票:0回答:7

我有一个 Android 应用程序,其中有一个主选项卡活动,以及各个选项卡中的多个活动。在我的主要活动的 onCreate() 中,我有一个可运行的对象来创建一个列表,并且在各个活动中,我使用这个列表。

在各个活动的onCreate()中,我也有对列表进行操作的Runnable。但是,我需要这些 Runnable 仅在主选项卡活动的 Runnable 完成创建列表时运行,否则我会得到一个空列表。我正在尝试找到一种优雅的方式来做到这一点。现在,在我的主要活动的 Runnable 中,我正在设置一个全局布尔变量 isDone,在我的个人活动的 Runnable 中,我正在等待通过 while 循环设置 isDone 。这可行,但可能不是最好的方法。

有什么想法吗?

谢谢。

编辑: 我正在尝试以下代码,但出现运行时错误:

在我的 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
java android
7个回答
20
投票

您可以使用

wait
notify
方法。

为此,需要有一些全局可访问的对象,其锁此时未被程序中的其他任何内容使用。我假设创建列表

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
,那么它对于第一个对象可以是隐式的(如上面的代码所示),但如果是活动,则需要在两种情况下显式使用活动对象。


13
投票

您可以像这样使用

Queue

public class RunQueue implements 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();
    } 
  }
}

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


9
投票

在主线程中设置一个值为1的CountDownLatch,然后让依赖线程等待它。当主线程完成后,您将锁存器倒数到 0,等待者将立即启动。


3
投票

使用

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


0
投票

您使用

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


0
投票

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

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

检查一下: https://gist.github.com/Petrakeas/ce745536d8cbae0f0761


0
投票

也许你可以参考Android中的Looper。简单地说,thead 在

while
循环中不断运行队列中的任务。

© www.soinside.com 2019 - 2024. All rights reserved.