使用 JNI 在创建时将(线程池的)所有本机 cpp 线程附加到 JVM 并仅在线程释放时分离的优点/缺点

问题描述 投票:0回答:1

我有一个 CPP ThreadMgr,它在初始化时创建 100 个 CPP 本机线程(线程池)。

现在,为了进行 JNI 调用并与 Java 交互,我必须使用 AttachCurrentThread 将线程附加到 JVM,并且在终止(正常或突然)这些线程之前,我必须 DetachCurrentThread。

我的方法是在创建时将所有本机线程(在本例中为 100 个)附加到 JVM,并且只有当我终止线程时,我才会将其与 JVM 分离。

在采用这种方法之前,我想列出其优点和缺点,以确定它是否是一个值得遵循的好方法。

我能想到的一些优点/缺点,

优点:

  1. 向 JVM 附加和分离本机线程会产生一些性能开销。通过在创建线程时附加一次并在终止前分离一次,与在线程内进行的每个 JNI 调用附加和分离相比,我们可以最大限度地减少这种开销。

缺点:

  1. 可能有些线程在其生命周期中永远不会进行任何 JNI 调用,但我仍然会进行将它们附加/分离到 JVM 的开销调用。

  2. 当一个线程附加到 JVM 时,它必须为附加线程分配一些资源,即使附加线程完成了所有 JNI 调用,只有在线程终止前分离时,资源才会释放。

如果我错过了这种方法的任何优点/缺点,以及这是否是一个值得遵循的好方法,请告诉我。

android c++ multithreading java-native-interface
1个回答
0
投票

优点:

  1. 向 JVM 附加和分离本机线程会产生一些性能开销。通过在创建线程时附加一次并 在终止前分离一次,我们可以最大限度地减少这种开销 与每次 JNI 调用的附加和分离相比 线程。

确实如此,但这种收益的重要性取决于工作量。如果附加和分离的开销相对于任务本身的主要工作来说很大,那么在该任务的上下文中,首先考虑使用线程池运行它的开销可能也是合适的。非常快的任务可能最好直接运行,而不是通过线程池。

  1. 想要访问 JVM 的任务不需要附加或分离自己。这使得任务更容易编写,并且因为它们不负责管理附加,所以降低了任务可能因附加但失败而导致问题的风险分离。然而,还有其他方法可以减轻这种风险。

缺点:

  1. 可能有些线程在其生命周期中永远不会进行任何 JNI 调用,但我仍然会进行附加/分离的开销调用 它们到 JVM。

是的。但是,如果您的线程池大小合理,并且总体工作足以证明线程池的合理性,那么该开销可能微不足道。

另一方面,如果在其生命周期内提交到池的任务中没有需要 JVM,那么根本不启动一个任务可能会节省大量资源。

    当线程附加到 JVM 时,即使附加线程已完成,它也必须为附加线程分配一些资源 对于所有 JNI 调用,只有在以下情况下才会释放资源: 线程在终止前被分离。
确实如此。事实上,当线程分离时,为 JVM 内的线程分配的资源甚至可能不会立即被清理。但这的重要性取决于很多因素,当然,它会随着附加线程的数量而变化。

  1. 您需要将 JVM 维护为全局资源。 任务只能利用拾取它的线程所附加到的 JVM,因此,如果任务本身不执行附加操作,则需要一种方法来获取持有它应该使用的 JVM。
总体而言,您提出的优缺点似乎都集中在性能问题上,但总的来说,性能取决于很多因素,并且很难预测。它需要被测量,如果它不充分,那么有效的调整需要基于测量到的实际瓶颈所在。

我认为您应该更多地关注更高层次的设计考虑,首先考虑线程池是否是满足您需求的最佳选择。如果您认为池确实合适,那么请考虑您是否真的需要或想要推出自己的池。我认为你可能不这样做,如果你不自己推出,那么这个问题很可能没有意义。无论如何,首先关注良好的设计,

然后编写良好的实现。

还要考虑可能存在可行的混合方法。例如,您可能想要维护单独的 JVM 附加线程池和非 JVM 附加线程池。或者,您可能希望池线程根据需要自适应地附加,然后保持附加状态直到池关闭。

© www.soinside.com 2019 - 2024. All rights reserved.