锁定Runnable直到完成

时间:2013-05-16 15:08:23

标签: java android multithreading

我在Android中使用Runnable作为循环。就这样:

    Timer timer = new Timer();
    timer.schedule(new looper(m_mainView, this),0, Rate);

每个'Rate'毫秒运行。

looper就是这样:

class looper extends TimerTask
{
    private ImageView img;
    Context c;


    public looper(ImageView imgView, Context context)
    {
        this.img = imgView;
        this.c = context;
    }

    public void run()
    {   
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
....

我想将代码锁定在run()中,直到它完成为止,如果在完成之前调用它,则调用的线程将返回并完成。

我在synchronized(Object)内尝试了run()方法但没有效果。还尝试了一个Mutex,它也没有用。

帮助:)

3 个答案:

答案 0 :(得分:1)

looper对象完全归timer.schedule所有,因此除了run之外,没有人可以调用该对象的timer.schedule方法。如果run方法花费的时间比指定的时间长,则很可能在完成之前再次调用run方法 - 特别是因为您已将任务的实际运行传递给UI线程。

你有两个简单的选择:

  1. run方法中设置一个标记,指示您正在运行,如果已设置run则不执行任何操作。
  2. 仅在固定延迟后关闭计时器,而不是重复时间。在跑步结束时,再次开火。
  3. 1:

    class Looper extends TimerTask {
      // ** Add this **
      volatile boolean running = false;
    
      public Looper() {
      }
    
      @Override
      public void run() {
        // ** Add this **
        if (!running) {
          running = true;
          try {
            runOnUiThread(new Runnable() {
              @Override
              public void run() {
              }
    
            });
            // ** Add this **
          } finally {
            running = false;
          }
    
        }
      }
    
    }
    

    第二种方法:

    timer.schedule(new looper(m_mainView, this, Rate),new Date());
    ...
    class Looper extends TimerTask {
      final long rate;
      final Looper looper;
    
      public Looper(long rate) {
        this.rate = rate;
        looper = this;
        // ...
      }
    
      @Override
      public void run() {
        runOnUiThread(new Runnable() {
          @Override
          public void run() {
            // ...
            new Timer().schedule(looper, new Date(new Date().getTime() + rate));
          }
    
        });
    
      }
    
    }
    

答案 1 :(得分:0)

您应该将synchronized添加到方法声明中,如下所示:

public synchronized void run()

答案 2 :(得分:0)

首先,为什么有再次调用run方法的风险?如果这是真的,那对我来说听起来就像是一种设计缺陷。 其次,代替TimerTask,您可能最好使用ScheduledExecutorService代替。这是以固定间隔执行计划任务的标准,最简单和最安全的方法。除了执行程序服务之外,您的用户代码将无法访问,您可以从中获取ScheduledFuture以获取返回值,以便您知道任务何时完成(调用get()时ScheduledFuture阻止)。 在实践中查看Java Concurrency for more ...