【问题标题】:Android/Java: How to call methods of an object created on a different thread?Android/Java:如何调用在不同线程上创建的对象的方法?
【发布时间】:2011-01-28 19:31:28
【问题描述】:

在我的 Android NDK 应用程序中,C++ 库在与 ui 线程不同的线程中运行。来自 C++ 的 JNI 调用创建 Java 类 Foo 的实例。我想在 UI 线程上创建另一个 Java 对象 Bar 来调用 Foo 上的方法。我怎么做?

难度奖励:Foo 有几个本地方法,它们从 C++ 库中调用相应的 JNI 函数。如何确保这些调用是线程安全的?

难度奖励2:Bar 的一些方法实际上是回调方法的覆盖,特别是WebViewClient。某些方法的返回码取决于调用 Foo 方法的结果。所以对 Foo 的调用需要立即发生。

【问题讨论】:

  • 事实上,需要线程同步结果的整个设计可能很糟糕。除非 JNI 库是旧版或第三方库,否则请考虑将 Foo 移至 UI 线程。
  • 您可能应该首先忽略通过 JNI 调用方法这一事实。线程安全问题与您使用的编程语言无关。
  • 难度奖励3!这都是正在开发的跨平台库的一部分。客户端主要使用 C++ 接口,它在 Android 上运行在与 UI 不同的线程上。这部分设计是不可变的,我无法访问。因此难以实施。

标签: java c++ android java-native-interface android-ndk


【解决方案1】:

试试 Handler 类。在 Foo 构造函数中构造一个 Handler。以某种方式传递对 Bar 类的引用。让 Bar 调用 Handler.post()。

为此,线程需要有一个消息队列。如果是纯粹的工作线程,那么直接调用方法不是答案;没有线程中断机制AFAIR。为了将东西传递给工作线程,您需要在某种程度上模拟消息队列 - 拥有一个 Runnnable 对象队列(Bar 将添加到该队列中)并不时检查它。

确保线程安全是一个单独的大问题。对于关于这个主题的所有言行,SO 都不够大。

【讨论】:

  • 我正在考虑使用某种消息队列,但我遇到了阻碍:Bar 的一些方法实际上是回调方法的覆盖,特别是 WebViewClient。某些方法的返回码取决于调用 Foo 方法的结果。所以对 Foo 的调用需要立即进行。我会将此详细信息添加到我的主要帖子中。
  • 所以线程阻塞是有序的。这很糟糕;让 UI 线程等待工作线程响应会扼杀线程的全部目的。更不用说非常脆弱(如果工人没有回应怎么办?)。也就是说,Object.wait() 和 notify() 方法是你的朋友(有时是敌人)。
【解决方案2】:

所以你有线程 1 和 2,线程 2 创建一个对象,线程 1 有一个对象想要调用线程 2 中的对象的方法。

难道你不能在线程 2 上使用标准的 java 线程同步技术(例如使用 synchronized 关键字)编写一个基本的对象吗?

例如线程上的java代码:

    // object of this type instantiated on thread 2 and called from thread 1
public class thread2Class  {
    public void doSomething(...) {
        synchronized (this) {
           // call java or jni mthod
        }
    }
 }

【讨论】:

    【解决方案3】:

    消息中嵌入通知回调例程的双消息队列。 线程 1 在线程 2 队列上发布带有回调地址的消息。 线程 2 处理消息并在线程 1 的队列上发布结果通知。 线程 1 调用与其发布的原始消息相关联的回调例程。 线程 1 队列是 UI 消息队列,线程 2 是您自己选择的队列实现。 线程 2 是库调用的管理器/包装器。 没有阻塞,没有等待。 如果线程 1 必须管理状态,则让它更新一个状态模型,该模型控制响应到达后发布的消息。

    【讨论】:

      【解决方案4】:

      我可能会尝试使用beginInvoke() 之类的东西以适当的方式将消息排队到线程中。已经注意到here 可以使用Activity.runOnUiThread() 或正确使用的AsyncTask() 来模拟beginInvoke()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-02
        • 1970-01-01
        • 2022-01-02
        • 1970-01-01
        • 1970-01-01
        • 2013-04-18
        • 2012-09-11
        相关资源
        最近更新 更多