Java创建线程的成本

655 阅读2分钟

我们知道在Java中创建线程整体上需要三步:

1.为线程堆栈分配并初始化一块内存区域

2.进行系统调用在OC中创建/注册一个本机线程

3.初始化线程文件描述符,并将其添加到JVM内部的数据结构中。

当考虑Java创建线程成本高的问题问题时首先要知道当new thread()时做了什么?

首先,我们知道Java中万物皆为对象,因此我们知道,new Object()过程必然包含在创建线程中。

然后,当执行new thread()时,除了执行了new Object()标准化过程外还执行了什么动作,我们知道Java中的线程与操作系统中的线程时一一对应的,因此创建一个线程还要调用操作系统内核API去创建新的线程。

JVM创建新线程时需要经历如下几步:

1.为线程栈分配内存,栈为该线程每个方法保存一个栈帧。

2.每个栈由一个常量数组、返回值、操作数堆栈和常量池组成

3.一些支持本机方法的JVM也会分配一个本机堆栈

4.每个线程获得一个程序计数器,告诉线程当前处理器的执行指令是什么

5.系统创建一个与Java线程对应的本机线程

6.将与线程相关的文件描述符增加到JVM内部数据结构中

7.线程共享堆和方法区。

我们使用Java 8来验证一下创建一个什么都不做的线程需要消耗多少空间和时间

java -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics -version

我们使用命令可以看到,16个线程,栈中reserved和committed共占16M左右,因此每个线程大约占1M

消耗时间,我们创建16个线程每个线程只获取当前状态需要的时间计时,共需要(end - start)ns

public class TestCreateThread {    
    public static void main(String[] args) {        
        long startTime=System.nanoTime();        
        for(int i = 0; i < 16; i++) {            
            Thread thread = new Thread(() -> {});            
            System.out.println(thread.getState());        
        }        
        long endTime=System.nanoTime();        
        System.out.println("strat " + startTime);        
        System.out.println("end   " + endTime);    
    }
}

strat 64396783831819

end 64396827362578

由结果可得出,16个线程创建需要 43,530,759ns = 43.5308ms