【发布时间】:2014-02-28 16:16:58
【问题描述】:
在我的后台服务中,我使用acquire()(不带参数)获取部分唤醒锁,并在我不再需要它时手动释放它。
当时,一些 Xperia 用户抱怨 Xperia 的耐力模式存在问题。我找到了这篇文章:Optimizing for Sony's Stamina Mode
- 不要使用唤醒锁 唤醒锁通常对功耗非常不利,因为它们使整个 Android 系统保持唤醒状态。如果使用了唤醒锁,请确保它们是定时唤醒锁,这样被占用的唤醒锁不会存在太长时间。计时您的唤醒锁,以便在您的任务完成后释放它。您可以在 Java Monday 的示例中看到它的使用情况。
所以我开始使用定时唤醒锁(使用acquire(timeout) 而不是acquire())。问题在于发布。我仍在手动释放,因为在大多数情况下,在超时到期之前我将不再需要锁。
问题在于自动释放。我会解释的。定时获取是这样实现的(取自 android-19 来源):
public void acquire(long timeout) {
synchronized (mToken) {
acquireLocked();
mHandler.postDelayed(mReleaser, timeout);
}
}
mReleaser 初始化如下(来自 android-19 来源):
private final Runnable mReleaser = new Runnable() {
public void run() {
release();
}
};
如果不再持有锁,release() 会抛出 RuntimeException:
public void release(int flags) {
synchronized (mToken) {
if (!mRefCounted || --mCount == 0) {
mHandler.removeCallbacks(mReleaser);
if (mHeld) {
try {
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
}
mHeld = false;
}
}
if (mCount < 0) {
throw new RuntimeException("WakeLock under-locked " + mTag);
}
}
}
所以问题是当我手动释放它时,它仍然会在超时到期后尝试自动释放它,并且唤醒锁处于未锁定状态。
问题是:我怎样才能仍然使用定时唤醒锁,同时能够在超时到期之前手动释放它?
【问题讨论】: