【问题标题】:Does oneway declaration in Android .aidl guarantee that method will be called in a separate thread?Android .aidl 中的 oneway 声明是否保证将在单独的线程中调用该方法?
【发布时间】:2010-06-14 23:45:25
【问题描述】:

我正在为 Android 手机的客户端/服务器应用程序设计一个框架。我对 Java 和 Android 都很陌生(但对一般编程或线程编程并不陌生)。

有时我的服务器和客户端会在同一个进程中,有时它们会在不同的进程中,具体取决于具体的用例。客户端和服务器接口如下所示:

IServer.aidl:

package com.my.application;

interface IServer {

    /**
     * Register client callback object
     */
    void registerCallback( in IClient callbackObject );

    /**
     * Do something and report back
     */
    void doSomething( in String what );
  .
  .
  .
}

IClient.aidl:

package com.my.application;

oneway interface IClient {

    /**
     * Receive an answer
     */
    void reportBack( in String answer );
  .
  .
  .
}

现在这里是有趣的地方。我可以预见客户端调用IServer.doSomething(),而后者又调用IClient.reportBack(),并根据反馈的内容,IClient.reportBack() 需要再次调用IClient.doSomething()

这里的问题是IServer.doSomething() 通常不会是可重入的。没关系,只要 IClient.reportBack() 总是在新线程中被调用。在这种情况下,我可以确保IServer.doSomething() 的实现始终是适当的synchronized,以便来自新线程的调用阻塞,直到第一个调用返回。

如果一切都按照我认为的方式运行,那么通过将 IClient 接口声明为oneway,我保证会如此。至少,我想不出从IServer.doSomething()IClient.reportBack() 的调用可以立即返回的任何方式(oneway 应该确保的),但IClient.reportBack 仍然能够以递归方式重新调用IServer.doSomething同一个线程。要么必须启动 IServer 中的新线程,要么旧的 IServer 线程可以重新用于对 IServer.doSomething() 的内部调用,但只有在对 IServer.doSomething() 的外部调用返回之后。

所以我的问题是,一切都按照我的想法进行吗? Android 文档几乎没有提到oneway 接口。

【问题讨论】:

    标签: java android multithreading aidl


    【解决方案1】:

    oneway 关键字意味着如果该调用导致 IPC(即调用者和被调用者在不同的进程中),则调用进程将不会等待被调用进程处理 IPC。如果它没有导致 IPC(即它们都在同一个进程中),则调用将是同步的。这是一个不幸的细节,大大简化了 binder IPC 的实现。如果它们在同一个进程中,则调用只是普通的 java 方法调用。

    【讨论】:

    • 谢谢。这就是我担心的问题。
    • 我已经构建了一个测试应用程序并确认您是正确的。当从不同的进程调用时,行为如文档所述——对单向接口中的方法的调用是异步的——但是当从同一个进程调用时,调用是同步的。
    【解决方案2】:

    来自 Android 文档

    oneway 关键字修改远程调用的行为。使用时,远程调用不会阻塞;它只是发送交易数据并立即返回。接口的实现最终从Binder线程池接收这个作为常规调用作为常规远程调用。如果 oneway 与本地调用一起使用,则没有影响,调用仍然是同步的

    例如,我们有一个Client app 和一个Server app,还有an AIDL interface 喜欢

    interface IRemoteService {
         oneway void onewayFunctionCall(int value); // function take 1 seconds to complete
         void noneOneWayFunctionCall(int value); // function take 1 seconds to complete
    }
    

    oneway影响Client app(远程调用)中的方法。
    比如我们从Client app调用服务器服务就像

    for (i in 0..5) {
        Log.i("TAG", "call $i") // fired each 1 second
        iRemoteService?.noneOneWayFunctionCall(i)
    }
    // run synchronous
    
    for(i in 0..5) {
        serverService.onewayFunctionCall(i); // fired right after previous function call
    }
    // run asynchronous
    

    因为单向方法调用并且不等待结果所以它必须是void function

    在上述情况下,我们从单个线程(主线程)调用server service,因此函数可以阻塞。所以我认为oneway 只在单个线程中有用。

    如果我们从客户端应用程序中的单个线程调用,服务器中的方法(oneway / none oneway)仍然同步执行。

    如果我们在客户端应用中使用多线程调用服务端服务,服务端中的方法会异步执行

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-01
      • 1970-01-01
      • 2015-01-21
      • 2023-03-04
      相关资源
      最近更新 更多