【发布时间】:2014-08-14 04:43:49
【问题描述】:
Android ContentProviders 使用“绑定线程”池来处理 RPC,例如 query、insert 和 call。在我对ContentProvider 的实现中,我正在执行一个可以使用Thread#interrupt() 中断的长时间运行的任务。我写了一个看门狗线程,在某些情况下会中断当前正在执行的绑定线程。中断正确生效,但现在我注意到当 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 binder 线程实际上处理线程中断的方式是否与 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);
}
});
【问题讨论】:
-
你能让我们看看你的代码吗?从阅读中很难分辨。
-
我添加了一些代码sn-ps,可以用来演示问题。
标签: android multithreading android-binder