自定义 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 并不能保证后台工作会停止,除非任务检查自己的状态。但是取消确实保证不会调用onProgressUpdateonPostExecute。如果onProgressUpdate 不足以在步骤之间更新您的 UI,请将每个步骤放入自己的任务中。

AsyncTask的一些提示:

他们至少更改了几次默认线程池。如果您想更好地控制执行,请使用executeOnExecutor 开始您的任务。

谨防持有对活动的引用。一个不好的建议(由一本广受好评的书 IIRC 推广)说给任务一个 WeakReference 给活动并在访问 UI 之前检查它。这是错误的,因为框架可能在调用onDestroy 后持有对活动的引用,并且当它清除其引用时,WeakReference 不会变为空,直到 GC 注意到活动不是强可达的。您应该在 Activity 中维护一组正在运行的任务,并在 Activity 暂停或销毁时取消它们。

要通过配置更改保持任务运行,请将它们托管在保留的无头片段中。

【讨论】:

以上是关于自定义 Runnable 实现,检查每行代码之间的 Thread.currentThread().isInterrupted()的主要内容,如果未能解决你的问题,请参考以下文章

Java基础学习 —— 线程

线程的实现方式二

Android 自定义TextView 实现文本间距

多个线程访问共享对象和数据的方式

java 22 - 9 多线程之 代码实现的方式2

题目24-多线程两种实现方式