如何按条件唤醒线程

时间:2015-04-08 14:04:23

标签: java android multithreading handler

我有一个活动正在运行,当然,在UI线程上,还有另一个线程在后台运行,并使用Handler post方法(通过looper)与活动进行通信。
当屏幕被打开或应用程序被隐藏时,它继续工作 所以我需要在onPause方法中停止这个线程并在onResume mehtod中唤醒它 在我的帖子中,我有条件暂停或停止 如何在onPause方法中让线程进入睡眠状态。并且在活动再次出现在前景之后将其唤醒 我可以使用监视器调用wait方法对一个对象执行此操作,然后通过此对象进行通知 但这是好方法吗?或者有另一种方式来优雅地做到这一点。

3 个答案:

答案 0 :(得分:2)

听起来像是使用旋转门的好地方。用一个许可证初始化一个信号量:

Semaphore turnstile = new Semaphore(1);

定期进行背景活动通过旋转栅栏,如下所示:

turnstile.acquire();
turnstile.release();

当前台线程希望后台线程在旋转门处暂停时,它可以锁定旋转门:

turnstile.acquire();

当前台线程希望后台线程再次开始工作时,它可以解锁 turntile():

turnstile.release();

良好的软件工程实践是将整个事情包装在Turnstile类中,并使用适当命名的方法来调用前台和后台线程。我将把它作为读者的练习。

答案 1 :(得分:1)

Android建议将服务用于长期后台任务,但如果您只是打开一个与Android生命周期相关的新线程,我不认为使用显示器和通话会很糟糕等待/通知。你能更具体地了解自己在做什么吗?

这是我如何停止和恢复已停止的线程的概述。 (您可能希望在您的实现中实现runnable)

class ThreadDemo extends Thread {
   private Object monitor; //This is the monitor
   private boolean keepRunning = true;
   private Thread t;

   ThreadDemo(){
       System.out.println("Creating thread");
   }

   public void callinOnResume(){
       synchronized(monitor){
           monitor.notify();
           }       
   }
   public void callinOnPause(){
           try {
                synchronized(monitor){
                    System.out.println(threadName +  "Waiting");
                    monitor.wait();
                }
            } catch (InterruptedException e) {
                System.out.println("Thread interrupted " + e.toString());
                }
    }

    public void run() {
       System.out.println("Starting to loop.");
        while (keepRunning) {
          //stuff
        }
        System.out.println("Done looping.");
    }

   public void start ()
   {
      System.out.println("Starting " +  threadName );
      if (t == null)
      {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
 }

答案 2 :(得分:0)

停止/恢复该线程之外的线程是一种不好的做法。线程必须决定何时运行以及何时停止。因此,后台线程应定期检查是否仍需要其工作,并且客户端(前台)线程应发出一些有关该信号的信号。 发出信号的一种方法是将信号形成为Runnable类型的作业,然后在线程池上执行它们。因此,当活动休眠时,它不会发出信号。

后台线程想要更​​新UI时的主要问题是目标Activity可以关闭(或者在重新创建过程中)并且更新任务失败。 AcyncTask类无法解决此问题。正确的解决方案发布在my Github workspace。但在使用此解决方案或其他解决方案之前,如果您确实需要后台线程,请三思而后行。最好的方法是根本不使用后台线程,直接在UI线程上进行所有UI更新。当然,如果从网络获取更新,则必须使用后台线程。