[정수리] 안드로이드 개발의 Thread 클래스 분석
7026 단어 안드로이드 개발
frameworks/base/include/utils/threads.h
class Thread : virtual public RefBase
{
public:
// Thread ,
Thread(bool canCallJava = true);
virtual ~Thread();
// , threadLoop
virtual status_t run(const char*name = 0, int32_t prority = PRIORITY_DEFAULT,
size_t stack = 0);
//
virtual void requestExit();
virtual status_t readyToRun();
// requestExit()
status_t requestExitAndWait();
// ,
status_t join();
protected:
// requestExit() true
bool exitPending() const;
private:
// , ,
// true , false
virtual bool threadLoop() = 0;
//
Thread& operator = (const Thread&);
// , run , threadLoop
static int _threadLoop(void* user);
const bool mCanCallJava;
thread_id_t mThread; // thread_id_t void*
mutable Mutex mLock;
Condition mThreadExitedCondition;
status_t mStatus;
// :
volatile bool mExitPending;
volatile bool mRunning;
sp<Thread> mHoldSelf;
};
먼저 Thread 클래스의 구조 함수를 살펴보겠습니다.
Thread::Thread(bool canCallJava)
: mCanCallJava(canCallJava),
mThread(thread_id_t(-1)),
mLock("Thrad::mLock"),
mStatus(NO_ERROR),
mExitPending(false), mRunnig(false)
{}
실제 스레드를 시작하는 함수:
status_t Thread::run(const char*name, int32_t priority, size_t stack)
{
Mutex::Autolock _l(mLock);
if(mRunnig)
return INVALID_OPERATION;
mState = NO_ERROR;
mExitPending = false;
mThread = thread_id_t(-1);
mHoldSelf = this; //
mRunning = true;
if (mCanCallJava)
res = createThreadEtc(_threadLoop, this, name, priority, stack, &mThread);
else
res = androidCreateRawThreadEtc(_threadLoop, this, name,
priority, stack, &mThread);
if(res == false) {
mStatus = UNKNOWN_ERROR;
mRunning = false;
mThread = thread_id_t(-1);
mHoldSelf.clear();
return UNKNOWN_ERROR;
}
return NO_ERROR;
}
mCanCallJava ?
inline bool createThreadEtc(thread_func_t entryFunction, void* userData,
const char* threadName = "android:unnamed_thread",
int32_t threadPriority = PRIORITY_DEFAULT,
size_t threadStackSize = 0,
thread_id_t *threadId = 0)
{
return androidCreateThreadEtc(entryFunction, userData, threadName, threadPriority,
threadStackSize, threadId) ? true : false;
}
int androidCreateThreadEtc(thread_func_t entryFunction,
void* userData,
const char* threadName,
int32_t threadPriority = PRIORITY_DEFAULT,
size_t threadStackSize = 0,
thread_id_t *threadId = 0)
{
return gCreateThreadFn(entryFunction, userData, threadName, threadPriority,
threadStackSize, threadId);
}
마지막으로 호출된 함수는 gCreateThreadFn이고 gCreateThreadFn은 전역 함수 지침입니다.static androidcreate_thread_fn gCreateThreadFn = androidCreateRawThreadEtc; 여기에 기본값은androidCreateRawThreadEtc입니다. 이것은 앞에서 호출한 것과 같습니다???
함수 포인터라면 값을 부여할 곳이 있을 것이다.
void androidSetCreateThreadFunc(android_create_thread_fn func)
{
gCreateThreadFn = func;
}
그럼 이 함수는 어디에서 호출되었습니까?또 무슨 값을 매겼을까?Android Runtime 클래스에서 가상 머신을 시작하는 위치를 찾았습니다.
int androidRuntime::startReg(JNIEnv* env)
{
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
return 0;
}
이렇게 하면 mCanCall Java가 true이면 다음과 같이 호출됩니다.
int AndroidRuntime::javaCreateThreadEtc(android_thread_func_t entryFunction,
void* userData,
const char* threadName,
int32_t threadPriority,
suze_t threadStackSize,
android_thread_id_t *threadId)
{
void** args = (void**)malloc(3*sizeof(void*));
args[0] = (void*)entryFunction;
args[1] = userData;
args[2] = (void*)strdup(threadName);
return androidCreateRawThreadEtc(AndroidRuntime::javaThreadShell, args.
threadName, threadPriority, threadStackSize, threadId);
}
마지막으로 호출된 것은 같은 라인을 만드는 함수입니다. 리셋 함수만 다릅니다. 여기는 안드로이드 런타임::javaThreadShell로 바뀌었습니다.
int AndroidRuntime::javaCreateThreadEtc(void* args)
{
voir* start = ((void**)args)[0];
voir* userData = ((void**)args)[1];
voir* name = ((void**)args)[2];
free(args);
JNIEnv* env;
javaAttachThread(name, &env);
result = (*(android_thead_func_t)start)(userData);
javaDetachThread();
free(name);
return result;
}
여기 스레드 함수javaThreadShell에서 앞에 있는 우리의 를 호출합니다threadLoop 함수는 호출하기 전에 자바 AttachThread () 를 호출하여 루트attach를 JNI 환경으로 가져갔습니다. 그러면 루트 함수는 JNI 함수를 호출할 수 있고, 마지막 루트 함수는 종료한 후에 자바 DetachThread () 를 호출하여 JNI 환경을 종료할 수 있습니다.
이제 스레드 함수로 들어갑니다threadLoop(), static 함수
int Thread::_threadLoop(void* user)
{
Thread* const self = static_cast<Thread*>(user);
sp<Thead> strong(self->mHoldSelf);
wp<Thead> weak(strong);
self->mHoldSelf.clear();
bool first = true;
do { // ,
bool result;
if (fisr) {
first = false;
self->mStatus = self->readyToRun();
result = (self->mStatus == NO_ERROR);
if (result && !self->exitPendind()) { //
result = self->threadLoop(); //
}
} else {
result = self->threadLoop();
}
{
Mutex::Autolock _l(self->mLock);
if (result == false || self->mExitPending) {
self->mExitPending = true;
self-mRunning = false;
self->mThread = thread_ir_t(-1);
self->mThreadExitedCondition.broadcast();
break;
}
}
strong.clear();
strong = weak.promote();
} while(strong != 0);
return 0;
}
여기서 루틴이 종료되는 조건은 다음과 같습니다: 1)result=true는 하위 클래스가 실행된threadLoop 함수에서false를 되돌려줍니다. 그러면 루틴이 주동적으로 종료됩니다. 2) mExidPendding =true 이 변수 값은 Thread 클래스의 RequestExit 함수로 설정되어 루틴이 수동적으로 종료됩니다.마지막으로 만약에 라인이 종료되면 초기화 작업을 하고 라인의 운행 상태를 설정해야 하며 방송은 이 라인에 관심이 있는 다른 대상을 알려준다.
, :
1) MyThread, Thead
2) MyThread threadLoop, pthread_create 。
3) MyThread thread, start() ,
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[Android] 둥글게 펼쳐지는 Ripple을, 바삭하게 구현간이적으로 터치 피드백이 없는 버튼이나 레이아웃, 탭 범위가 좁아져 버린 버튼 등에, 범위 밖으로 둥글게 퍼지는 Ripple로 탭감, 영역을 조금 늘립니다. 이런 느낌 (화질 나쁘고 미안해..) Ripple을 내고 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.