gpt4 book ai didi

android - Binder 线程中断意外行为

转载 作者:行者123 更新时间:2023-11-29 01:39:57 39 4
gpt4 key购买 nike

Android ContentProvider 使用“绑定(bind)线程”池来处理 RPC,例如 queryinsertcall。在我的 ContentProvider 实现中,我正在执行一项长时间运行的任务,该任务可使用 Thread#interrupt() 中断。我写了一个看门狗线程,在某些情况下会中断当前正在执行的 Binder 线程。中断正确生效,但现在我注意到当 android 再次使用它来处理新的 RPC 时,binder 线程仍然设置了它的中断标志。这会导致新 RPC 的行为就好像它被中断了一样。我没想到这一点。我捕获了 InterruptedException 但如果看门狗线程在 RPC 结束时设置了中断标志,而没有任何东西正在查看或清除标志,则可能会发生这种情况。

ExecutorService 的一些临时测试表明,当它重用线程来处理任务时,它会在运行每个任务之前的某个时间重置中断标志。我在 ThreadPoolExecutor 类中找到了这条评论:

 * 2. Before running any task, the lock is acquired to prevent
* other pool interrupts while the task is executing, and
* clearInterruptsForTaskRun called to ensure that unless pool is
* stopping, this thread does not have its interrupt set.

为了纠正 android 的行为,我想在每个 ContentProvider RPC 的开始我用 Thread.interrupted() 清除中断标志,但这看起来不像最优雅的解决方案。

任何人都可以确认 android 绑定(bind)器线程实际上是否以不同于 ExecutorService 的方式处理线程中断,什么可能是最好的解决方法,这样中断标志就不会在不同的 RPC 之间传播?

这里有一些代码可以放在 ContentProvider 中以重现问题:

@Override
public Bundle call(String method, String arg, Bundle extras) {
Log.w(TAG, "Thread "+ Thread.currentThread().getName() + " before isInterrupted()=" + Thread.currentThread().isInterrupted());

final Thread callThread = Thread.currentThread();

if (method.equals("interrupt")) {
new Thread("interrupter") {
@Override
public void run() {
callThread.interrupt();
}
}.start();
}

try {
Thread.sleep(500);
} catch (InterruptedException e) {
Log.w(TAG, e);
Thread.currentThread().interrupt();
}

Log.w(TAG, "Thread "+ Thread.currentThread().getName() + " after isInterrupted()=" + Thread.currentThread().isInterrupted());

return null;
}

然后在 Activity 中(确保它在与 ContentProvider 不同的进程中运行!)连接两个按钮,一个执行常规调用,一个执行常规调用执行一个会触发中断的调用:

findViewById(R.id.call).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getContentResolver().call(CallContentProvider.CONTENT_URI, "", "", null);
}
});

findViewById(R.id.callint).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getContentResolver().call(CallContentProvider.CONTENT_URI, "interrupt", "", null);
}
});

最佳答案

到目前为止,这是我解决此问题的最佳方法:

private volatile Thread mRunningCallThread;

@Override
public Bundle call(String method, String arg, Bundle extras) {
Thread.interrupted(); // Clear interrupted flag

mRunningCallThread = Thread.currentThread(); // Thread to interrupt

// Do stuff, allowing interruption by another thread

mRunningCallThread = null;

Thread.interrupted(); // Clear interrupted flag
}

mRunningCallThread 字段是指向我可能会中断的当前运行线程的指针。

关于android - Binder 线程中断意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25300256/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com