要想知道什么是线程,那就得先知道进程是什么,因为线程是存在于进程中的,它本身是不会独立存在的。进程是系统进行资源分配和调度的基本单位。线程与进程的关系,进程中至少存在一个线程,进程中的多个线程共享这个进程的资源。
在Java中,我们启动Main函数的时候就是启动了一个JVM的进程。这个进程中的线程我们叫做主线程。
public static void main(String[] args) {
System.out.println ("这是主线程");
}
进程和线程的关系图如下所示。
由图我们可以知道,一个进程中是存在多个线程的,每个线程有自己的程序计数器和栈,多个线程共享进程的堆和方法区资源。程序计数器和栈是“线程私有”的内存区域。
程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器,就是执行的指令地址。由于多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的(时间片轮转方式),在任何一个确定的时刻,一个处理器(对于多核处理器来说就是一个内核)都只会执行一条线程中的指令,所以,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,每条线程之间计数器互不影响,独立存储,这就解释为什么程序计数器设计为线程私有的。
每个线程都有自己的栈资源,用于存储该线程的局部变量,这些局部变量是该线程私有的,其他线程是访问不了的,除此之外栈还用来存放线程的调用栈帧。栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区的虚拟机栈(Virtual Machine Stack)的栈元素。栈帧存储了方法的局部变量表,操作数栈,动态连接和方法返回地址等信息。一个方法从调用开始到执行完成,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
堆是一个进程中最大的一块内存,是被所有线程共享的,是进程创建时就分配的,所有的对象实例以及数组都是在堆上分配的。
方法区与堆一样,也是被所有线程共享的的内存区域,它用于存储已被JVM加载的类信息、常量、静态变量等。