1.系统进程
学习操作系统的时候,接触了一个概念叫做进程,简单讲下,进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。进程在操作系统上有唯一的ID,当进程结束后,这个ID可以被重用,在Linux机器上我们使用top命令,可以可到系统上运行的进程信息,同样在Windows机器上我们可以打开任务管理器面板查看进程信息。对于普通用户来讲,把电脑上打开的一个软件看做一个进程即可。
切回主题,进程在运行过程中会有状态切换,其中涉及到的状态,就绪态、运行态、阻塞态
就绪态(Ready):进程已获得除处理器外的所需资源,等待分配处理器资源,只要分配了处理器进程就可执行。
运行态(Running):进程已获取运行时所需资源,并且操作系统分配时间片给该进程,占用处理器资源执行相关操作。
阻塞态(Blocked):进程等待某种运行时所需资源(如I/O操作或同步)。
2.系统线程
后来在学习中又认识了系统线程,简单讲下,线程有时被称为轻量进程(Lightweight Process,LWP),是程序执行流的最小单元。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但是它可以和属与同一个进程的其它线程共享进程所拥有的全部资源。在操作系统中,线程被视为轻量级进程,所以操作系统中线程的状态实际上和进程状态是一致的模型。
3.Java线程
铺垫这么久终于到了今天的主题Java线程,有些朋友可能疑惑,系统线程和Java线程不一样么?是的,Java线程是JVM基于操作系统线程模型自己实现的,和操作系统中的线程有着对应关系,大家可以找相关文章参考一下,这里就不在赘述了。推荐文章:
https://blog.csdn.net/cringkong/article/details/79994511 《Java线程和操作系统线程的关系》
https://my.oschina.net/goldenshaw/blog/705397 《Java 线程状态之 RUNNABLE》
以前我一直以进程状态那套来理解Java线程状态,虽然没有犯过大错,但在实际应用中却遇到了一些问题,毕竟人家JVM在设计上有申明虚拟机中的线程状态,不反应任何操作系统线程状态。Java线程状态有六种,包括新建、可运行、阻塞、期限等待、无期限等待、结束。
新建状态(NEW):创建后尚未启动的线程处于这个状态,即该线程对象被new出来但是没有调用其start()方法。
可运行状态(RUNNABLE):包括了操作系统线程状态中的Running和Ready,甚至包括部分Blocked状态,也就是处于此状态的线程可能正在运行,也可能正在等待系统资源,如等待CPU为它分配时间片,如等待网络IO读取数据。
阻塞(BLOCKED):线程被挂起了,原因通常是它在等待一个锁,当尝试进入一个synchronized语句块/方法时,锁已经被其它线程占有,就会被阻塞。
无限期等待(WAITING):处于这种状态的线程不会被分配CPU执行时间,它们要等待显示的被其它线程唤醒,这种状态通常是指一个线程拥有对象锁后进入到相应的代码区域后,调用相应的锁对象的wait()方法操作后产生的结果。。
限期等待(TIMED_WAITING):处于这种状态的线程也不会被分配CPU执行时间,不过无需等待被其它线程显示的唤醒,在一定时间之后它们会由系统自动的唤醒。
结束(TERMINATED):已终止线程的线程状态,线程已经结束执行(正常或异常的退出)。
最后,附上我自己写的Demo用来查看不同的Java线程的状态,配合使用jps命令和jstack命令。
/**
* Created by lgf on 2018/11/1.
*/
public class TestThreadState {
static ReentrantLock lock = new ReentrantLock();
static Object monitor = new Object();
static Object waiter = new Object();
public static void main(String[] args) throws InterruptedException {
// 线程1 模拟锁
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
while (true) {
}
}
});
thread1.setName("test thread 1");
thread1.start();
Thread.sleep(1000L);
// 线程2 模拟等待锁释放
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
while (true) {
}
}
});
thread2.setName("test thread 2");
thread2.start();
// 线程3 模拟休眠sleep
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread3.setName("test thread 3");
thread3.start();
// 线程4 模拟限期等待wait
Thread thread4 = new Thread(new Runnable() {
@Override
public void run() {
try {
synchronized (waiter) {
waiter.wait(1000000L);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread4.setName("test thread 4");
thread4.start();
// 线程5 模拟synchronized
Thread thread5 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (monitor) {
while (true) {
}
}
}
});
thread5.setName("test thread 5");
thread5.start();
Thread.sleep(1000L);
// 线程6 模拟等待synchronized
Thread thread6 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (monitor) {
while (true) {
}
}
}
});
thread6.setName("test thread 6");
thread6.start();
Thread.sleep(1000L);
// 线程7 模拟等待无限期wait
Thread thread7 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (waiter) {
try {
waiter.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread7.setName("test thread 7");
thread7.start();
Thread.sleep(1000L);
// 线程8 模拟正常运行
Thread thread8 = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
}
}
});
thread8.setName("test thread 8");
thread8.start();
}
}
运行程序,打开命令行输入jps -lmv 得到该进程的pid。
命令行输入jstack -l pid 得到该进程的堆栈信息。