2011-01-28 3 views
3

내 Android NDK 앱에서 C++ 라이브러리는 UI 스레드와 다른 스레드에서 실행됩니다. C++의 JNI 호출은 Java 클래스 Foo의 인스턴스를 생성합니다. Foo에서 메소드를 호출하기 위해 UI 스레드에서 작성된 다른 Java 객체 Bar를 갖고 싶습니다. 어떻게해야합니까?Android/Java : 다른 스레드에서 생성 된 객체의 메소드를 호출하는 방법은 무엇입니까?

난이도 보너스 : Foo에는 C++ 라이브러리에서 해당 JNI 함수를 호출하는 몇 가지 기본 메소드가 있습니다. 이러한 호출이 스레드로부터 안전한지 확인하려면 어떻게해야합니까?

어려움 보너스 2 : Bar의 메서드 중 일부는 실제로 콜백 메서드, 특히 WebViewClient를 재정의합니다. 일부 메소드의 리턴 코드는 Foo의 메소드 호출 결과에 따라 달라집니다. 따라서 Foo에 대한 호출은 즉시 발생해야합니다.

+0

실제로 동기 결과가 스레드에서 필요로하는 전체 디자인은 악취가 날 것입니다. JNI 라이브러리가 레거시 또는 제 3자인 경우가 아니면 Foo를 UI 스레드로 이동하는 것을 고려하십시오. –

+0

JNI를 통해 메서드가 호출된다는 사실을 무시함으로써 시작해야합니다. 스레드 안전성 문제는 사용중인 프로그래밍 언어에 크게 의존하지 않습니다. – fadden

+0

난이도 보너스 3! 이것은 모두 개발중인 크로스 플랫폼 라이브러리의 일부입니다. 클라이언트는 주로 UI와는 다른 스레드에서 실행되는 C++ 인터페이스를 사용합니다.디자인의이 부분은 나에게 불변이고 접근 할 수 없다. 따라서 이것을 구현하는 데 따른 어려움. – djcouchycouch

답변

0

처리기 클래스를 사용해보십시오. Foo 생성자에서 Handler를 생성합니다. 어떻게 든 Bar 클래스에 대한 참조를 전달하십시오. Bar가 Handler.post()를 호출하도록하십시오.

이 기능을 사용하려면 스레드에 메시지 큐가 있어야합니다. 순전히 작업자 스레드 인 경우 메서드를 직접 호출하는 것은 대답이 아닙니다. AFAIR 스레드 인터럽트 메커니즘이 없습니다. 작업 스레드에 물건을 전달하려면 메시지 대기열을 다소 시뮬레이트해야합니다. 즉, Bar가 추가 할 Runnnable 객체의 대기열을 가지고 수시로 검사해야합니다.

스레드 안전성을 보장하는 것은 큰 문제입니다. SO는이 주제에 대해 말하고 행해진 모든 것에 대해 충분히 크지 않습니다. 그래서

+0

메시지 대기열을 사용하려고 생각했지만 showstopper에서 문제가 발생했습니다. Bar의 메서드 중 일부는 실제로 WebViewClient의 콜백 메서드를 재정의합니다. 일부 메소드의 리턴 코드는 Foo의 메소드 호출 결과에 따라 달라집니다. 따라서 Foo에 대한 호출은 즉시 발생해야합니다. 나는이 세부 사항을 내 메인 포스트에 추가 할 것이다. – djcouchycouch

+0

그래서 스레드 차단이 순서입니다. 이것은 상당히 빤다; 작업자 스레드가 응답하도록 UI 스레드가 대기하는 것은 스레드의 모든 목적을 죽입니다. 말할 것도없이 매우 부서지기 쉽습니다 (작업자가 응답하지 않으면 어떻게됩니까?). 즉, Object.wait() 및 notify() 메소드는 친구 (때로는 적)입니다. –

0

당신이 스레드 1과 2를 가지고는, 스레드 2는 객체를 생성하고 스레드 1은 2

당신이 작성된 스레드 2에 기본적으로 개체가 없습니다 스레드 방법에게 개체를 호출하고자하는 목적을 가지고 동기화 된 키워드를 사용하는 것과 같은 표준 자바 스레드 동기화 기술과 자바? 스레드에서

예를 들어 자바 코드 : 메시지에 포함 통지 콜백 루틴

// 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 
     } 
    } 
} 
0

더블 메시지 큐. 스레드 1은 콜백 주소가있는 메시지를 스레드 2 큐에 게시합니다. 스레드 2는 메시지를 처리하고 스레드 1의 큐에 결과 알림을 게시합니다. 스레드 1은 게시 한 원래 메시지와 관련된 콜백 루틴을 호출합니다. 스레드 1 큐는 UI 메시지 큐이고 스레드 2는 자신이 선택한 큐 구현입니다. 스레드 2는 라이브러리 호출의 관리자/래퍼입니다. 차단하지 않고 기다릴 필요가 없습니다. 스레드 1이 상태를 관리해야하는 경우 응답이 도착하면 게시 할 메시지를 제어하는 ​​상태 모델을 업데이트해야합니다.

0

아마 beginInvoke()과 같은 것을 활용하여 메시지를 적절한 방식으로 스레드에 대기열에 넣으려고합니다. herebeginInvoke()Activity.runOnUiThread() 또는 올바르게 활용 된 AsyncTask()으로 조롱 될 수 있다고 언급되었습니다.

관련 문제