当前位置: 首页 > 面试题库 >

终止正在运行本机代码的线程

高胜
2023-03-14
问题内容

在我的应用程序中,我对一些本机代码进行了包装,这是通过JNI桥调用的。此本地代码需要在单独的线程中执行(并行处理)。但是,问题在于代码有时“挂起”,因此线程需要“强制”终止。不幸的是,我还没有找到任何“微妙的”方法来这样做:一般建议是告诉线程中的代码正常退出,但是我无法使用此本地代码(以上均为第三方代码)来执行此操作。

我使用Java Concurrent API进行任务提交:

Future<Integer> processFuture = taskExecutor.submit(callable);

try {
    result = processFuture.get(this.executionTimeout, TimeUnit.SECONDS).intValue();
}
catch (TimeoutException e) {
    // How to kill the thread here?
    throw new ExecutionTimeoutException("Execution timed out (max " + this.executionTimeout / 60 + "min)");
}
catch (...) {
    ... exception handling for other cases
}

Future#cancel()只会中断线程,但不会终止线程。因此,我使用了以下技巧:

class DestroyableCallable implements Callable<Integer> {

    private Thread  workerThread;

    @Override
    public Integer call() {
        workerThread = Thread.currentThread();

        return Integer.valueOf(JniBridge.process(...));
    }

    public void stopWorkerThread() {
        if (workerThread != null) {
            workerThread.stop();
        }
    }
}

DestroyableCallable callable = new DestroyableCallable();

Future<Integer> processFuture = taskExecutor.submit(callable);

try {
    result = processFuture.get(this.executionTimeout, TimeUnit.SECONDS).intValue();
}
catch (TimeoutException e) {
    processFuture.cancel(true);
    // Dirty:
    callable.stopWorkerThread();

    ThreadPoolTaskExecutor threadPoolTaskExecutor = (ThreadPoolTaskExecutor) taskExecutor;

    logger.debug("poolSize: " + threadPoolTaskExecutor.getPoolSize() + ", maxPoolSize:"
                    + threadPoolTaskExecutor.getMaxPoolSize() + ", activeCount:"
                    + threadPoolTaskExecutor.getActiveCount());
    }

    throw new ...;
}
catch (...) {
    ... exception handling for other cases
}

与此代码有关的问题/问题:

  • 通常这样做是否正确?还有其他更优雅的选择吗?
  • activeCount 任务执行程序上的操作没有减少,因此任务执行程序仍然“认为”线程正在运行
  • 我不得不在方法上添加workerThread != null检查stopWorkerThread(),因为这个变量null在某些情况下是存在的。我不明白这些情况是什么…

笔记:

  • 本机代码不占用文件描述符(套接字)。一切都作为数据块传递给它,并以相同的方式返回。
  • 本机代码占用大量CPU。即使保证终止,也可能需要很长时间。

赏金编辑 :重新访问本机代码的方法/建议很明确,请不要在答复中提供。我需要纯Java解决方案/解决方法。


问题答案:

Java具有用于强制终止线程的纯选项。它是仅适用于Thread.stop()的古老且已弃用的(AFAIK)。而且 没有 安全
终止线程的选项(这就是为什么不建议使用.stop(),并且甚至不允许JVM实现者实现的原因)。

原因是应用程序内的所有线程 共享 内存和资源-
因此,如果您在任意点强制终止线程,则无法确定哪个终止线程不会使某些共享内存/资源处于不一致状态。而且,您甚至不能(通常)假设 哪些
资源(可能)是脏的(因为您不知道确切的线程停止位置)。

因此,如果您希望应用程序的某些线程能够被中断,则唯一的解决方案是在设计阶段提供“保存点”的某些表示法,即目标线程代码中的位置,保证不会改变共享的位置状态,因此线程在此处退出是安全的。这正是javadocs
Thread.stop()所告诉的:安全地中断线程的唯一方法是设计线程的代码,以便它本身可以响应某种中断请求。某种标志,由线程不时检查。

我试图告诉您:您无法完成有关使用Java线程/并发的要求。我可能建议您的方法(在此处提供)是在单独的过程中完成工作。强制终止进程比线程安全得多,因为1)进程彼此之间的间隔更大,并且2)OS在进程终止后会处理许多清理工作。杀死进程并不完全安全,因为存在某种类型的资源(例如文件),默认情况下OS不会清除它们,但就您而言,这似乎是安全的。

因此,您可以设计一个单独的小应用程序(甚至可以在Java中使用-
如果您的第三方lib不提供其他绑定,甚至在shell脚本中也可以),这仅是让您进行计算。您可以从主应用程序启动该过程,完成任务,然后启动看门狗。看门狗检测到超时-
强制杀死进程。

这是解决方案的唯一草案。如果您想提高性能(启动过程可能需要一些时间),则可以实现某种类型的进程池,等等。



 类似资料:
  • 本文向大家介绍C语言如何正确的终止正在运行的子线程,包括了C语言如何正确的终止正在运行的子线程的使用技巧和注意事项,需要的朋友参考一下 最近开发一些东西,线程数非常之多,当用户输入Ctrl+C的情形下,默认的信号处理会把程序退出,这时有可能会有很多线程的资源没有得到很好的释放,造成了内存泄露等等诸如此类的问题,本文就是围绕着这么一个使用场景讨论如何正确的终止正在运行的子线程。其实本文更确切的说是解

  • 本文向大家介绍C#实现终止正在执行的线程,包括了C#实现终止正在执行的线程的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#实现终止正在执行的线程的实现方法,并针对一些容易出错的地方进行了深入分析,具体方法如下: 一般来说,很多人都会使用Abort方法来终止线程,其实这种做法并不可取!如果你的线程正在操作临界资源,很有可能会造成资源没有正确释放而出现死锁问题。正确的做法应该是使用标记来终

  • 问题内容: 我正在使用Python启动程序。 在某些情况下,程序可能会冻结。这是我无法控制的。我从命令行启动时唯一可以做的就是迅速杀死程序。 有什么办法可以模仿吗?我正在用来启动程序。 问题答案: 请查看该模块上的文档以了解更多信息:http : //docs.python.org/2/library/subprocess.html

  • 问题内容: codepad.org允许您在线运行C,C ++,D等代码,但不能运行Java …我可以使用Java的网站吗? 问题答案: 还有http://ideone.com/(支持多种语言)

  • 我有一个正在运行的Spark应用程序,它占据了所有核心,而我的其他应用程序将不会被分配任何资源。 我做了一些快速的研究,人们建议使用YARN kill或 /bin/spark-class来杀死命令。然而,我使用的是CDH版本, /bin/spark-class根本不存在,YARN kill应用程序也不起作用。 有人能和我一起吗?