1. 多线程
一个Java程序从 main()
方法开始执行,看似没有其他线程参与,但实际上Java程序天生就是多线程程序。
如何查看是哪些多线程?
public static void main(String[] args) {
// 获取Java线程管理MXBean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// 不需要获取同步的monitor和synchronizer信息,仅获取线程和线程堆栈信息
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
// 遍历线程信息,仅打印线程ID和线程名称信息
for (ThreadInfo threadInfo : threadInfos) {
System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.
getThreadName());
}
}
2. 线程的优先级
从 Thread
类中可以看到:
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
优先级的范围从1~10,在线程构建的时候可以通过 setPriority(int)
方法来修改优先级,默认优先级是5。
注意:在不同的 JVM 以及操作系统上,线程规划会存在差异,有些操作系统甚至会忽略对线程优先级的设定
3. 线程的状态
状态 | 说明 |
---|---|
新建(New) | 创建后尚未启动。 |
可运行(Runnable) | 可能正在运行,也可能正在等待 CPU 时间片。 |
阻塞(Blocked) | 等待获取一个排它锁,如果其线程释放了锁就会结束此状态。 |
无限期等待(Waiting) | 等待其它线程显式地唤醒,否则不会被分配 CPU 时间片。 |
限期等待(Timed Waiting) | 无需等待其它线程显式地唤醒,在一定时间之后会被系统自动唤醒。 |
如何查看进程中线程的状态呢?
这里使用 jps + jstack
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) {
try {
TimeUnit.SECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 该线程在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 {
public void run() {
synchronized (Blocked.class) {
while (true) {
try {
TimeUnit.SECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
//通过可以jps+jstack可以看到如下结果:
// 等待 "BlockedThread-1" 释放对象锁
"BlockedThread-2" #15 prio=5 os_prio=0 tid=0x000000001eae1000 nid=0x5ae8 waiting for monitor entry [0x000000002092f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at chapter4.ThreadState$Blocked.run(ThreadState.java:48)
- waiting to lock <0x000000076b799e40> (a java.lang.Class for chapter4.ThreadState$Blocked)
at java.lang.Thread.run(Thread.java:748)
// 首次进入同步块,获取了对象锁,进行waiting
"BlockedThread-1" #14 prio=5 os_prio=0 tid=0x000000001eadf000 nid=0xa4f8 waiting on condition [0x000000002082f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at chapter4.ThreadState$Blocked.run(ThreadState.java:48)
- locked <0x000000076b799e40> (a java.lang.Class for chapter4.ThreadState$Blocked)
at java.lang.Thread.run(Thread.java:748)
// 等待 唤醒
"WaitingThread" #13 prio=5 os_prio=0 tid=0x000000001eade000 nid=0xb058 in Object.wait() [0x000000002072f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076b797708> (a java.lang.Class for chapter4.ThreadState$Waiting)
at java.lang.Object.wait(Object.java:502)
at chapter4.ThreadState$Waiting.run(ThreadState.java:34)
- locked <0x000000076b797708> (a java.lang.Class for chapter4.ThreadState$Waiting)
at java.lang.Thread.run(Thread.java:748)
// timed waiting
"TimeWaitingThread" #12 prio=5 os_prio=0 tid=0x000000001ead8000 nid=0xa35c waiting on condition [0x000000002062e000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at chapter4.ThreadState$TimeWaiting.run(ThreadState.java:20)
at java.lang.Thread.run(Thread.java:748)
6个状态的转换如下图:
4. Daemon线程
当 JVM 中没有非Daemon线程时,JVM 需要退出。此时所有的 Daemin 线程立即终止
栗子:
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new DaemonRunner(), "DaemonRunner");
thread.setDaemon(true);
thread.start();
TimeUnit.SECONDS.sleep(1);
}
static class DaemonRunner implements Runnable {
@Override
public void run() {
try {
System.out.println("start");
SleepUtils.second(10000);
System.out.println("end");
} finally {
System.out.println("DaemonThread finally run.");
}
}
}
Output:
start
next : 线程的启动与终止