当前位置: 首页 > 知识库问答 >
问题:

在后台线程内终止长时间运行的任务

龚钧
2023-03-14

我有一个压缩图像的任务,它在图像中使用了许多循环:

private void writeCompressedData() {
    int i, j, r, c, a, b;
    loat[][] inputArray;

    for (r = 0; r < minBlockHeight; r++) {
        for (c = 0; c < minBlockWidth; c++) {
            xpos = c * 8;
            pos = r * 8;
            for (comp = 0; comp < jpegObj.numberOfComponents; comp++) {
                inputArray = (float[][]) jpegObj.components[comp];

                 for (i = 0; i < jpegObj.VsampFactor[comp]; i++) {
                     for (j = 0; j < jpegObj.HsampFactor[comp]; j++) {
                         xblockoffset = j * 8;
                         yblockoffset = i * 8;
                         for (a = 0; a < 8; a++) {
                             for (b = 0; b < 8; b++) {
                                 // Process some data and put to inputArray
                             }
                         }

                         // Encode Huffman block 
                     }
                 }
             }
         }
     }
}

我在普通线程中运行此方法,如下所示:

new Thread(new Runnable() {
    @Override
    public void run() {
        writeCompressedData();
    }
});

或者在后台工作线程中运行

TaskExecutor.queueRunnable(new Runnable() {
    @Override
    public void run() {
        writeCompressedData();
    }
});

问题是:这种方法有时会出错,在接收无效输入时会导致无限循环。在这种情况下,它将永远运行,并损害CPU,即使当设备的屏幕关闭时,这会增加设备的温度(如果我使用工作线程,它还会阻止等待队列中的其他任务)。

我想我需要设置一个超时来终止长时间运行的任务。在正常Java线程中实现这一点的最佳方法是什么?RxJava支持吗?

我知道我需要修复的是“错误”的方法,而不仅仅是终止它。但对于大型应用程序来说,很难控制其他开发人员的代码,我需要做的第一件事就是避免影响用户。

共有3个答案

杜思远
2023-03-14

更好的方法是在不同的进程中运行这样的代码。即使进程崩溃,主进程也将不受影响。

裴泰平
2023-03-14

您可以使用JavaExecutorServiceFuture来解决这个问题。请参阅这篇文章。

裴焱
2023-03-14

你需要某种形式的合作取消,比如检查线程。currentThread()。isInterrupted()位于一个或多个嵌套循环内。

for (/* ... */) {
    if (Thread.currentThread().isInterrupted()) return;

    for (/* ... */) {

        if (Thread.currentThread().isInterrupted()) return;

        for (/* ... */) {
            // the tightest loop
        }             
    }
}

然后当您运行该方法时,保留Thread/Future调用中断/取消(true)

backgroundTask = new Thread(() -> method());
backgroundTask.start();
// ...
backgroundTask.interrupt();

backgroundFuture = executorService.submit(() -> method());
// ...
backgroundFuture.cancel(true);

在RxJava中,这看起来像这样:

backgroundDisposable = Completable.fromAction(() -> method())
.subscribeOn(Schedulers.io()) // dedicated thread recommended
.observeOn(AndroidSchedulers.mainThread())
.subscribe(() -> { /* done */ }, e -> { /* error */ });

// ...
backgroundDisposable.dispose();
 类似资料:
  • 我对Python和Django相当陌生,所以请让我知道是否有更好的方法来做到这一点。我想做的是拥有每个设备(从模型继承。Model)启动一个长时间运行的后台线程,该线程不断检查该设备的运行状况。然而,当我运行代码时,它似乎不像守护进程那样执行,因为服务器缓慢且不断超时。这个后台线程将(在大多数情况下)运行程序的生命周期。 下面是我代码的简化版本: 这似乎是线程的一个非常简单的用法,但每次我寻找解决

  • 问题内容: 我正在为我的学校创建一个应用程序,该应用程序应每n分钟检查一次网站上是否有新标记。为此,当用户首次登录时,实际标记的编号将保存在“ UserDefaults”中。当应用终止时,n分钟后,将重新计算标记的数量,并将其与前一个标记进行比较,并在更改数量时发送通知。 我想知道是否有一种方法可以执行此任务。我尝试在-applicationWillTerminate-中创建一个计时器,但只触发了

  • 我有一个在Tomcat7上运行的Spring3.0WebMVC应用程序。在应用程序启动时,我启动一个后台线程来加载内存缓存,其中包含来自数据库的记录。该线程从数据库加载所有数据通常需要一个多小时。在同一个应用程序中,我有一个@Controller注释类,它公开了一个REST接口,客户端可以通过该接口从加载的缓存中获取对象。 我们的要求之一是,在数据加载完成之前发出的任何REST请求都将立即向客户端

  • 我正在使用rxjava将一些任务上载到服务器,每当任务启动的片段或活动被销毁时,我都会处理订阅以避免内存泄漏,但我想要的是,即使在片段/活动被销毁后,我也需要继续在后台运行任务,有什么方法可以实现这一点吗? 实例 是否必须始终释放订阅?如果不是,何时使用dispose?

  • Android系统如何处理长时间运行的后台任务?开发人员能否依赖系统保持活动的未绑定服务?

  • 问题内容: 我是python和线程的新手。我已经编写了充当网络爬虫的python代码,并在网站中搜索特定的关键字。我的问题是,如何使用线程同时运行类的三个不同实例。当实例之一找到关键字时,所有三个实例都必须关闭并停止爬网。这是一些代码。 如何使用线程让Crawler同时执行三个不同的爬网? 问题答案: 似乎没有一种(简单的)方法可以终止Python中的线程。 这是一个并行运行多个HTTP请求的简单