【问题标题】:wakelock inside a running thread Android正在运行的线程Android中的唤醒锁
【发布时间】:2012-11-12 14:27:09
【问题描述】:

我有一个简单的问题:

在一个服务中,我需要运行另外 2 个彼此独立的线程,并且我需要一个唤醒锁来让它们被执行。我举个例子:

   wl.aquire();

    if (true) {
        mExecutorService.execute(thread1);
    }

    if (true) {
        mExecutorService.execute(thread2);
    }
   wl.release();

那么,在这种情况下,唤醒锁将在 2 个线程启动后释放还是等待它们完成?

如果没有,我需要唤醒锁在它们运行时保持运行,并且只有在最后一个线程完成时才释放它。我怎样才能做到这一点?我是否必须在线程体内获取新的唤醒锁?

谢谢

【问题讨论】:

    标签: android multithreading wakelock


    【解决方案1】:

    根据Executor execute() 文档:“在未来某个时间执行给定的命令。该命令可以在新线程、池线程或调用线程中执行,由 Executor 实现自行决定。”

    所以这取决于你使用的是哪个具体的 Executor。

    我认为您应该使用submit() 为执行者分配新工作。

    如果您坚持使用 Executor,则在 submit() 返回的 Future 上调用 get() 将阻塞,直到结果可用。

    所以你可以打电话:

    Future<Result> result_1 = mExecutorService.execute(Runnable1);
    Future<Result> result_2 = mExecutorService.execute(Runnable2);
    
    result_1.get();
    result_2.get();
    

    或者,您可以启动两个线程并等待它们完成:

    Thread t1 = new Thread(Runnable1);
    Thread t2 = new Thread(Runnable2);
    t1.start();
    t2.start();
    
    t1.join();
    t2.join();
    

    希望这会有所帮助。

    【讨论】:

    • 绝对是正确的方法。对了,不是executor.submit()而不是execute()吗?
    • 最后我添加了一个新的唤醒锁部分,因为等待执行器获取(),让我遇到了“强制关闭,等待”问题。顺便说一句,谢谢你的回答。这应该是正确的方式
    【解决方案2】:

    假设您从AsyncTask 或后台线程运行此代码。在调用wl.release();之前,您可以在所有线程上调用[Thread.join()]

    查看link 了解join() 详细信息

    EDIT1:在执行器上,您还可以使用具有长等待值的awaitTermination() 来等待它完成所有任务。以下代码来自官方java doc

    void shutdownAndAwaitTermination(ExecutorService pool) {
       pool.shutdown(); // Disable new tasks from being submitted
       try {
         // Wait a while for existing tasks to terminate
         if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
           pool.shutdownNow(); // Cancel currently executing tasks
           // Wait a while for tasks to respond to being cancelled
           if (!pool.awaitTermination(60, TimeUnit.SECONDS))
               System.err.println("Pool did not terminate");
         }
       } catch (InterruptedException ie) {
         // (Re-)Cancel if current thread also interrupted
         pool.shutdownNow();
         // Preserve interrupt status
         Thread.currentThread().interrupt();
       }
     }
    

    【讨论】:

    • 谢谢。那可能是一个解决方案。因此,对于 executor,我们可以使用 .get() 命令。所以你是说唤醒锁在线程启动时立即释放?
    【解决方案3】:

    参见http://developer.android.com/reference/android/os/PowerManager.WakeLock.html——正确的方法是在你正在运行的两个线程中获取唤醒锁。给定您的示例代码,您将需要在 thread1 和 thread2 中使用一个成员变量来存储唤醒锁,以及传递唤醒锁的某种方式,可能像这样:

    thread1.setWakelock(wl);
    thread2.setWakelock(wl);
    
    class Thread implements Runnable {
        PowerManager.Wakelock mWakelock;
        void setWakelock(PowerManager.Wakelock wl) {
            mWakelock = wl;
        }
    }
    

    然后在thread1和thread2中,你需要:

    run() {
        mWakelock.acquire();
        ... your existing code here ...
        mWakelock.release();
    }
    

    请注意,这将起作用,因为默认情况下唤醒锁是引用计数的;请参阅 PowerManager.WakeLock.setReferenceCounted()。

    使用 thread.join() 等待线程完成是错误的;如您所见,它将阻塞 UI 线程,您将获得 ANR。

    【讨论】:

    • 这就是我决定开发它的方式。我在其 cunstructors 中制作了一个带有 WakeLock 参数的自定义 Runnable。只需检查它是否保留在 run() 方法上,然后我获取 WL
    猜你喜欢
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 2020-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    • 1970-01-01
    相关资源
    最近更新 更多