基本概念
Java 线程其实是映射到操作系统的内核线程上的,所以 Java 线程基本上也就是操作系统在进行管理。在 Linux系统中,线程和进程用的是同一个结构体进行描述的,只不过进程拥有自己独立的地址空间,而同一个进程的多个线程之间是共享资源的。
简单说明: 本文基于 openjdk 1.8 进行
线程状态
每种线程状态的切换条件, 以及调用方法如下图所示 :
线程具有一下几种状态 Java 的线程状态在 Thread.State 枚举中定义代码如下
public enum State {
//新创建,未启动
NEW,
//在jvm 中运行,也可能正在等待操作系统的其他资源
RUNNABLE,
//阻塞,并且正在等待监视器锁
BLOCKED,
//处于等待状态的线程,正在等待另一个线程执行特定的操作
WAITING,
//限期等待, 可以设置最大等待时间
TIMED_WAITING,
//结束
TERMINATED;
}
线程创建
- 继承 Thread 类, 代码如下:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
// 启动线程
PrimeThread p = new PrimeThread(143);
p.start();
- 实现 Runable 接口, 代码如下 (通常推荐使用这种方式):
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
// 启动线程
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
hotspot 源码
JNI 机制
JNI 是 Java Native Interface 的缩写,它提供了若干的 API 实现了Java和其他语言的通信(主要是C和C++)。
JNI的适用场景
当我们有一些旧的库,已经使用C语言编写好了,如果要移植到Java上来,非常浪费时间,而JNI可以支持Java程序与C语言编写的库进行交互,这样就不必要进行移植了。或者是与硬件、操作系统进行交互、提高程序的性能等,都可以使用JNI。需要注意的一点是需要保证本地代码能工作在任何Java虚拟机环境。
JNI的副作用
一旦使用JNI,Java程序将丢失了Java平台的两个优点:
- 程序不再跨平台,要想跨平台,必须在不同的系统环境下程序编译配置本地语言部分。
- 程序不再是绝对安全的,本地代码的使用不当可能会导致整个程序崩溃。一个通用规则是,调用本地方法应该集中在少数的几个类当中,这样就降低了Java和其他语言之间的耦合。
举个例子
这块操作比较多,可以参考如下的资料
https://www.runoob.com/w3cnote/jni-getting-started-tutorials.html
启动流程
启动流程如下
线程启动
Java 创建线程 Thread 实例之后,是通过 start 方法进行启动该线程,通知执行。在 start 方法的内部,调用的是 start0() 这个本地方法。我们可以从该方法为入口分析 JVM 对于 Thread 的底层实现。
public synchronized void start() {
// 判断线程状态
if (threadStatus != 0)
throw new IllegalThreadStateException();
// 添加到组
group.add(this);
boolean started = false;
try {
// 启动线程
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this