自定义 Runnable 实现,检查每行代码之间的 Thread.currentThread().isInterrupted()
Posted
技术标签:
【中文标题】自定义 Runnable 实现,检查每行代码之间的 Thread.currentThread().isInterrupted()【英文标题】:Custom Runnable implementation that checks for Thread.currentThread().isInterrupted() between every line of code 【发布时间】:2018-09-16 21:16:12 【问题描述】:我正在尝试实现一个可以管理传入的 Runnable 并取消任何 Runnable 的类,无论它们在代码中的什么位置,保证。
例如,在 android 中,我希望能够执行以下操作。
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
manager.submit(new Runnable()
@Override
public void run()
someLongRunningTaskThatCallsTheUi();
);
@Override
public void onPause()
manager.cancel(); // cancels all Runnables to avoid issues with calling the UI
如果 Future 的 cancel()
方法实际上并不能保证 Runnable 代码的取消并且 ExecutorService 的 shutdownNow()
有同样的问题,我该如何解决这个问题?
据我所知,我需要在要调用的每一段 UI 代码之前添加对 Thread.currentThread().isInterrupted()
的检查,并退出该方法以避免以某种方式进一步调用。
【问题讨论】:
您可能可以通过某种直接的字节码操作或代码编织来做到这一点。撇开这些黑暗艺术不谈,您所要求的根本不是线程如何工作。 当我遇到这个问题时,我就有这样的印象。那么有没有更好的方法来解决这个问题?我想通过单击按钮在后台启动长时间运行的操作,但也允许用户在需要时退出,取消操作。 这些Runnables
是您自己编写的,还是您应用的第三方插件?
我正在写它们。我只是不想将if (isInterrupted) return;
放在可运行的多个位置。这感觉像是一种非常脆弱的代码编写方式。
AsyncTask
不起作用有什么原因吗?取消它不会停止不检查状态的后台工作,但它确实保证不会在 UI 线程中发生进一步的回调。对于具有多个步骤的流程,完成一项任务可以开始下一项任务。
【参考方案1】:
考虑使用AsyncTask
。取消AsyncTask
并不能保证后台工作会停止,除非任务检查自己的状态。但是取消确实保证不会调用onProgressUpdate
和onPostExecute
。如果onProgressUpdate
不足以在步骤之间更新您的 UI,请将每个步骤放入自己的任务中。
AsyncTask
的一些提示:
他们至少更改了几次默认线程池。如果您想更好地控制执行,请使用executeOnExecutor
开始您的任务。
谨防持有对活动的引用。一个不好的建议(由一本广受好评的书 IIRC 推广)说给任务一个 WeakReference
给活动并在访问 UI 之前检查它。这是错误的,因为框架可能在调用onDestroy
后持有对活动的引用,并且当它清除其引用时,WeakReference
不会变为空,直到 GC 注意到活动不是强可达的。您应该在 Activity 中维护一组正在运行的任务,并在 Activity 暂停或销毁时取消它们。
要通过配置更改保持任务运行,请将它们托管在保留的无头片段中。
【讨论】:
以上是关于自定义 Runnable 实现,检查每行代码之间的 Thread.currentThread().isInterrupted()的主要内容,如果未能解决你的问题,请参考以下文章