本文共 4928 字,大约阅读时间需要 16 分钟。
一个Java程序从main()方法开始执行,然后按照既定的代码逻辑执行,看似没有其他线程参与,但实际上Java程序天生就是多线程程序,因为执行main()方法的是一个名称为main的线程。
下面使用JMX来查看一个普通的Java程序包含哪些线程:
public class MultiThread { public static void main(String[] args) { //获取Jva线程管理MXBean ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); //不需要获取同步的monitor和synchronized信息,仅获取线程和线程堆栈信息 ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false); //遍历进程信息,仅打印线程ID和线程名称信息 for(ThreadInfo threadInfo : threadInfos ){ System.out.println("[" + threadInfo.getThreadId() + "]" + threadInfo.getThreadName()); } }}
输出如下:
[6]Monitor Ctrl-Break //Idea独有,因为Idea使用反射机制执行代码,与此同时会创建一个Monitor Ctrl-Break的线程用于监控的目的。[5]Attach Listener //该线程是负责接收到外部的命令,执行该命令,并且把结果返回给发送者。通常我们会用一些命令去要求jvm给我们一些反馈信息,如:java -version、jmap、jstack等等。如果该线程在jvm启动的时候没有初始化,那么,则会在用户第一次执行jvm命令时,得到启动。[4]Signal Dispatcher //第一个Attach Listener线程的职责是接收外部jvm命令,当命令接收成功后,会交给signal dispather线程去进行分发到各个不同的模块处理命令,并且返回处理结果。signal dispather线程也是在第一次接收外部jvm命令时,进行初始化工作。[3]Finalizer // JVM在垃圾收集时会将失去引用的对象包装成Finalizer对象(Reference的实现),并放入ReferenceQueue,由Finalizer线程来处理;最后将该Finalizer对象的引用置为null,由垃圾收集器来回收。[2]Reference Handler //清除Reference的线程,它主要用于处理引用对象本身(软引用、弱引用、虚引用)的垃圾回收问题。[1]main //主线程
在Java中,通过一个整型成员变量priority来控制优先级,优先级的范围从1 ~ 10,在线程构建的时候可以通过setPriority(int) 方法来修改优先级,默认优先级为5,优先级高的线程分配时间片的数量多于优先级低的线程。
注意:不同JVM以及操作系统上,线程规划存在差异,有些系统甚至会忽略对线程优先级的设定。
Java线程在运行的生命周期中可能处于下表所示的6种不同状态,在给定的一个时刻,线程只能处于其中的一个状态。
状态名称 | 说明 |
---|---|
NEW | 初始状态,线程被构建,但是还没有调用start()方法 |
RUNNABLE | 运行状态,Java线程将操作系统中的就绪和运行两种状态笼统的称为“运行中” |
BLOCKED | 阻塞状态,表示线程被阻塞 |
WAITING | 等待状态,表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程做出一些特定动作(通知或中断) |
TIME_WAITING | 超时等待状态,该状态不同于WAITING,它是可以在指定的时间自行返回的 |
TERMINATED | 终止状态,表示当前线程已经执行完毕 |
示例:
package pers.zhang.part4;import jdk.nashorn.internal.ir.Block;/** * @author zhang * @date 2020/1/15 - 22:15 * 线程状态 */public class ThreadState { public static void main(String[] args) { new Thread(new TimeWaiting(), "TimeWaitingThread").start(); new Thread(new Waiting(), "WaitingThread").start(); //使用两个Blocked线程,一个获取锁成功,另一个被阻塞 new Thread(new Blocked(), "BlockedThread-1").start(); new Thread(new Blocked(), "BlockedThread-2").start(); } //该线程不断的睡眠 static class TimeWaiting implements Runnable{ @Override public void run() { while(true){ SleepUtils.second(100); } } } //该线程在Waiting.class实例上等待 static class Waiting implements Runnable{ @Override public void run() { while(true){ synchronized(Waiting.class){ try{ Waiting.class.wait(); }catch (InterruptedException e){ e.printStackTrace(); } } } } } //该线程在Blocked.class实例上加锁后,不会释放锁 static class Blocked implements Runnable{ @Override public void run() { synchronized (Blocked.class){ while(true){ SleepUtils.second(100); } } } }}package pers.zhang.part4;import java.util.concurrent.TimeUnit;/** * @author zhang * @date 2020/1/15 - 22:20 */public class SleepUtils { public static final void second(long seconds){ try { TimeUnit.SECONDS.sleep(seconds); } catch (InterruptedException e) { e.printStackTrace(); } }}
运行程序,然后再终端或者命令提示符中:键入“jps”,输出如下:
//进程Id每次都不同12424 Launcher191482604 Jps28476 ThreadState
再次键入"jstack 28476(对应自己的)",部分输出如下:
//用于监控非daemon线程,只有daemon线程时,退出JVM。正常运行中!"DestroyJavaVM" #15 prio=5 os_prio=0 tid=0x0000000002f42800 nid=0x6610 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE//BlockedThread-1获取到了Blocked.class的锁"BlockedThread-2" #14 prio=5 os_prio=0 tid=0x0000000019026800 nid=0x30bc waiting on condition [0x0000000019e6e000] java.lang.Thread.State: TIMED_WAITING (sleeping)//BlockedThread-1线程阻塞在获取Blocked.class示例的锁上"BlockedThread-1" #13 prio=5 os_prio=0 tid=0x0000000019026000 nid=0x72e8 waiting for monitor entry [0x0000000019d6f000] java.lang.Thread.State: BLOCKED (on object monitor)//WaitingThread线程在Waiting实例上等待"WaitingThread" #12 prio=5 os_prio=0 tid=0x0000000019022000 nid=0x67d4 in Object.wait() [0x0000000019c6f000] java.lang.Thread.State: WAITING (on object monitor)//TimeWaitingThread线程处于超时等待状态"TimeWaitingThread" #11 prio=5 os_prio=0 tid=0x000000001901f800 nid=0x36d0 waiting on condition [0x0000000019b6e000] java.lang.Thread.State: TIMED_WAITING (sleeping)
Java线程状态变迁
转载地址:http://uypqb.baihongyu.com/