本文旨在对Android中的多线程做一个简单阐述
0.虚拟机的本质
在开始讨论之前,我们需要明确一下什么是虚拟机。虚拟机顾名思义,是一个可以模拟硬件的程序。虚拟机模拟的硬件包括但不限于:CPU,加法器,寄存器,函数栈。当我们有一一个虚拟机A,和一段程序B的时候,B的运行过程如下:首先启动虚拟机A(Java里面可以理解为一个C++程序)然后A加载B的代码文件,把代码文件解析为指令,这些指令一般都是自定义的和汇编指令很类似,这些指令大概有:操作栈,操作寄存器,加法,设置PC等等。具体理解虚拟机的概念可以通过这个文档:自己实现一个虚拟机

理清虚拟机的概念有助于我们明白这样一个事实:在Java里面创建线程之后,其实是通过指令映射到了操作系统的线程。
1.线程概念
线程本质上是CPU的一个指令执行流程,当有多个任务需要执行的时候,当某个指令流需要等待硬件资源的时候可以切换到下一个指令流继续执行。由于Java是虚拟机模式,因此在Java层和操作系统层都会有自己的执行流和栈。我们可以这样理解这个关系:Java的线程是操作系统线程的一个封装。


线程和进程在Linux平台上很类似,其基本的创建指令是一样的,但是共享的程度不一样,例如线程之间能够共享内存,这导致了线程之间能够比进程之间更加高效的通信。
在一般的UI系统中,一般会有主线程来处理UI和用户输入相关的事情,其他业务交给子线程处理。这样的系统通常是这样运作的:系统启动的时候主线程初始化完成之后开始事件循环,在Android里面这个过程叫做Lopper,当有系统事件或者输入就使用select或者epoll技术唤醒主线程处理主事件队列里面的事件,耗时任务就分配给子线程处理。
因此我们可以总结如下:
- 线程是内核调度的基本单位,是一个指令执行流程
- 线程的调度和创建都需要资源
- 多线程能够更好的利用硬件资源
- 多线程之间通信更容易
2.Thread对象
为什么是Thread
Android目前兼容了Java8的大部分语法,并且适配了OpenJDK的大部分库,因此适用于Java的语言基础设施也可以适用于Android,因此可以在Android使用Java里面的基础设置来运行线程,这就是我们这里需要讨论的Thread对象。当然构成Java多线程的框架的组件还有很多,例如Feature,Callable,Runable这里我们只讨论最基础的Thread。
Thread的原理
从第一点我们能够知道最本质的线程是操作系统对指令的调度,那么当我们创建一个Thread对象并且绑定一个Runable的时候,这个对象怎么和操作系统的指令调度映射呢。查看Android ART源码我们可以发现:Thread.start实际上调用了POSIX里面的线程相关接口,例如pthread_create,回调的任务即Runable被封装到了Native层的对象上,当线程开始执行的时候就会调用这个Runable的对象Run方法,因此完成了线程调度。
void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon) {
CHECK(java_peer != nullptr);
Thread* self = static_cast<JNIEnvExt*>(env)->GetSelf();
Runtime* runtime = Runtime::Current();
Thread* child_thread = new Thread(is_daemon);
child_thread->tlsPtr_.jpeer = env->NewGlobalRef(java_peer);
stack_size = FixStackSize(stack_size);
env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
reinterpret_cast<jlong>(child_thread));
int pthread_create_result = 0;
if (child_jni_env_ext.get() != nullptr) {
pthread_t new_pthread;
pthread_attr_t attr;
CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), stack_size);
pthread_create_result = pthread_create(&new_pthread,&attr,Thread::CreateCallback,child_thread);
CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), "new thread");
}
}
void* Thread::CreateCallback(void* arg) {
Thread* self = reinterpret_cast<Thread*>(arg);
Runtime* runtime = Runtime::Current();
{
ObjPtr<mirror::Object> receiver = self->tlsPtr_.opeer;
jmethodID mid = WellKnownClasses::java_lang_Thread_run;
ScopedLocalRef<jobject> ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
InvokeVirtualOrInterfaceWithJValues(soa, ref.get(), mid, nullptr);
}
Runtime::Current()->GetThreadList()->Unregister(self);
return nullptr;
}
整个线程创建和调度的过程可以总结如下:

至此我们知道了Thread怎么和操作系统映射的,接下来我们还会探讨一下线程的竞争和协作。