1.线程的运行状态 在Java中,线程的状态一共是6种状态,分别是
NEW:初始状态,线程被构建,但是还没有调用start方法
RUNNABLED:运行状态,JAVA线程把操作系统中的就绪和运行两种状态统一称为“运行中”
BLOCKED:阻塞状态,表示线程进入等待状态,也就是线程因为某种原因放弃了CPU使用权,阻塞也分为几种情况
等待阻塞:运行的线程执行wait方法,jvm会把当前线程放入到等待队列
同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被其他线程锁占用了,那么jvm会把当前的线程放入到锁池中
其他阻塞:运行的线程执行Thread.sleep或者t.join方法,或者发出了I/O请求时,JVM会把当前线程设置为阻塞状态,当sleep结束、join线程终止、io处理完毕则线程恢复
WAITING: 等待状态
TIME_WAITING:超时等待状态,超时以后自动返回
TERMINATED:终止状态,表示当前线程执行完毕
2.线程生命周期图
3.线程的终止
3.1 线程的中断需要外部干预情况
线程中存在无限循环执行,比如while(true)循环
线程中存在一些阻塞的操作,比如sleep、wait、join等
3.2 stop方法终止
调用stop方法去强行中断,那么这个时候相当于是发送一个指令告诉操作系统把这个线程结束掉,
但是操作系统的这个结束动作完成不代表线程 中的任务执行完成,很可能出现线程的任务执行了一般被强制中断,最终导致数据产生问题。
这种行为 类似于在linux系统中执行 kill -9类似,它是一种不安全的操作。
3.3 interrupt 方法
我们把while(true)改成while(flag),这 个flag可以作为共享变量被外部修改,修改之后使得循环条件无法被满足,从而退出循环并且结束线程。
当其他线程通过调用当前线程的interrupt方法,表示向当前线程打个招呼,告诉他可以中断线程的执行了,至于什么时候中断,取决于当前线自己。线程通过检查自身是否被中断来进行相应,可以通过isInterrupted()来判断是否被中断。
处于阻塞状态下的线程中断
我们平时在线程中使用的sleep、wait、join等操作,它都会抛出一个 InterruptedException异常,为什么会抛出异常,是因为它在阻塞期间,必须要能够响应被其他线程发起中断请求之后的一个响应,而这个响应是通过InterruptedException来体现的。
但是这里需要注意的是,在这个异常中如果不做任何处理的话,我们是无法去中断线程的,因为当前的异常只是响应了外部对于这个线程的中命令,同时线程的中断状态也会复位,如果需要中断,则还 需要在catch中添加下面的代码
4.线程占用cpu过高排查
通过 jps 命令,查看java进程的pid
通过jstack 查看线程日志
通过 top -c 动态显示进程及占用资源的排行榜,从而找到占用CPU最高的进程PID,得到的PID=80972
#top -c
然后再定位到对应的线程, top -H -p 80972 查找到该进程中最消耗CPU的线程,得到PID=81122
#top -H -p 80972
通过 printf “0x%x\n” 81122 命令,把对应的线程PID转化为16进制
#printf "0x%x\n" 81122
截止执行这个命令 jstack 80972 | grep -A 20 0x13ce2 查看线程Dump日志,其中-A 20表示
展示20行, 80972表示进程ID, 0x13ce2表示线程ID
#jstack 80972 | grep -A 20 0x13ce2
5.并发和并行
并发:是指多个任务在同一时间段内交替执行的能力。当多个任务共享同一资源,并且它们的执行时间有重叠时,就可以实现并发。
并行:是指多个任务在同一时刻同时执行的能力。
QPS(每秒查询数)是指系统在一秒内能够处理的查询请求数量。查询请求可以是数据库查询、API调用、HTTP请求等。
TPS(每秒事务数)是指系统在一秒内能够处理的事务数量。事务可以是数据库中的读写操作、网络请求、交易等。