并发系列(1)之 Thread 详解
本文主要结合 java.lang.Thread
源码,梳理 Java 线程的整体脉络;
一、线程概述
对于 Java 中的线程主要是依赖于系统的 API 实现的,这一点可以从 java.lang.Thread
;源码中关键的方法都是 native
方法看出,也可以直接查看 OpenJDK 源码看出来,这一点后面还会讲到;对于 JDK1.8 而言,他的 Windows 版和 Linux 版使用的都是 1:1 线程模型,即系统内核线程和轻量级进程的比是 1:1
;
- 内核线程(Kernel-Level Thread,KLT):是由操作系统内核(Kernel)直接支持的线程,这种线程由内核来完成切换,内核通过调度器(Schedule)进行调度,并负责将线程的任务映射到各个处理器上;
- 轻量级进程(Light Weight Process,LWP):程序可以直接使用的一种内核线程高级接口,也就是我们通常意义上的线程;
如图所示:
优点:
- 由内核线程的支持,每个线程都成为一个独立的调度单元,即线程之间不会相互阻塞影响;使用内核提供的线程调度功能及处理器映射,可以完成线程的切换,并将线程的任务映射到其他处理器上,充分利用多核处理器的优势,实现真正的并行。
缺点:
- 同时由于基于内核线程实现,线程的创建、关闭、同步等操作都需要系统调用;需要在用户态和内核态之间切换,代价相对较高;
- 另外每个线程都需要消耗一定的内核资源,如内核线程的栈空间,所以系统支持的轻量级进程是有限的;
二、线程状态
Java 线程的整个生命周期可能会经历以下5中状态,如图所示:
- 新建(New):新建后未启动的线程;
- 运行(Runnable):包括运行中(Running)和就绪(Ready)两种状态;也就是正在运行,或者等待 CPU 分配执行时间;
- 等待(Waiting):无限期的等待其他线程显示唤醒;
- 超时等待(Timed_Waiting):一定时间内没有被其他线程唤醒,则由系统自动唤醒;
- 阻塞(Blocked):等待获取排它锁;
- 终止(Terminated):运行终止;
三、源码分析
1. native注册
/* Make sure registerNatives is the first thing <clinit> does. */
private static native void registerNatives(); static { registerNatives(); }
这段代码在很多地方都出现过,比如:
java.lang.System
java.lang.Object
java.lang.Class
其作用就是在使用 JNI 时需要向 JVM 注册,其方法名默认为 Java_<fully qualified class name>_method
;但是如果觉得这样的名字太长,这是就可以使用 registerNatives()
向 JVM 注册任意的函数名;
扫描二维码关注公众号,回复:
6004129 查看本文章
Thread 中的 native 方法有:
private native void start0(); private native void stop0(Object o); public final native boolean isAlive(); private native void suspend0(); private native void resume0(); private native void setPriority0(int newPriority); public static native void yield(); public static native void sleep(long millis) throws InterruptedException; public static native Thread currentThread(); public native int countStackFrames(); private native void interrupt0(); private