線程信息查看
public class ThreadInfoTest {
public static void main(String[] args) {
//獲取java線程管理mxbean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
//不需要獲取同步的monitor和synchronizer信息 僅獲取線程和線程堆棧
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
for (ThreadInfo threadInfo : threadInfos) {
System.out.println("[" + threadInfo.getThreadId() + "]" + threadInfo.getThreadName() );
}
}
}
[9]Monitor Ctrl-Break
[5]Attach Listener
[4]Signal Dispatcher
[3]Finalizer
[2]Reference Handler
[1]main 用戶程序入口
可以看到一個java程序運行不僅僅是main()方法運行,而是main線程和多個其他線程同時運行.
線程的狀態
public static void main(String[] args) {
new Thread(new TimeWaiting(),"TimeWaitingThread").start();
new Thread(new Waiting(),"waitingthread").start();
new Thread(new Blocked(),"blocked thread -1 ").start();
new Thread(new Blocked(),"blocked thread -2 ").start();
}
static class TimeWaiting implements Runnable {
@Override
public void run() {
while (true){
try {
TimeUnit.SECONDS.sleep(12);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Waiting implements Runnable{
@Override
public void run() {
while (true){
synchronized (Waiting.class){
try {
Waiting.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
static class Blocked implements Runnable{
@Override
public void run() {
synchronized (Blocked.class){
while (true){
try {
TimeUnit.SECONDS.sleep(12);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
"blocked thread -2 " prio=6 tid=0x00000000070f2800 nid=0x1c14 waiting for monitor entry [0x0000000007eff000]
**blocked thread -2 阻塞在獲取鎖上**
java.lang.Thread.State: BLOCKED (on object monitor)
at concurrent.ThreadState$Blocked.run(ThreadState.java:60)
- waiting to lock <0x000000077e351470> (a java.lang.Class for concurrent.ThreadState$Blocked)
at java.lang.Thread.run(Thread.java:662)
"blocked thread -1 " prio=6 tid=0x00000000070c5800 nid=0x14bc waiting on condition [0x0000000007dff000]
**blocked thread -1 獲取到了鎖**
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:302)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:328)
at concurrent.ThreadState$Blocked.run(ThreadState.java:60)
- locked <0x000000077e351470> (a java.lang.Class for concurrent.ThreadState$Blocked)
at java.lang.Thread.run(Thread.java:662)
"waitingthread" prio=6 tid=0x00000000070c4800 nid=0x1c38 in Object.wait() [0x0000000007cff000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000077e34cc88> (a java.lang.Class for concurrent.ThreadState$Waiting)
at java.lang.Object.wait(Object.java:485)
at concurrent.ThreadState$Waiting.run(ThreadState.java:43)
- locked <0x000000077e34cc88> (a java.lang.Class for concurrent.ThreadState$Waiting)
at java.lang.Thread.run(Thread.java:662)
"TimeWaitingThread" prio=6 tid=0x0000000007148800 nid=0x1718 waiting on condition [0x0000000007bff000]
**該線程處於超時等待**
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:302)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:328)
at concurrent.ThreadState$TimeWaiting.run(ThreadState.java:26)
at java.lang.Thread.run(Thread.java:662)
java線程在運行的生命週期中可能處於6中不同的狀態,在給定的一個時刻線程只能處於其中的一個狀態.
狀態名稱 | 說明 |
---|---|
NEW | 初始狀態線程被構建但是還沒有調用start()方法 |
Runnable | 運行狀態java線程將操作系統中的就緒和運行倆種狀態統稱爲運行中 |
BLOCKED | 阻塞狀態 表示線程阻塞於鎖 |
WAITING | 等待狀態 表示線程進入等待狀態 進入該狀態表示當前線程需要等待其他線程做出一些特定的動作 例如通知或中斷 |
TIME_WAITING | 超時等待狀態 該狀態不同於waiting 他是可以在指定的時間自行返回的 |
TERMINATED | 終止狀態 表示當前線程已經執行完畢 |
知識點:
阻塞狀態是線程阻塞在進入synchronized關鍵字修飾的方法或代碼塊時的狀態,但是阻塞在java.concurrent包中Lock接口的線程狀態卻是等待狀態,因爲java.concurrent中的Lock接口對於阻塞的實現均實現了LockSupport類中的相關方法.
Daemon線程
Daemon線程是一種支持型線程 因爲它主要被用作程序中後臺調度以及支持性工作 這意味着 當一個java虛擬機中不存在非daemon線程的時候 java虛擬機將會退出
public static void main(String[] args) {
Thread thread = new Thread(new DaemonRunner(),"daemon runner");
thread.setDaemon(true);
thread.start();
}
static class DaemonRunner implements Runnable {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("daemon thread finally run");
}
}
}
main線程啓動了Daemonrunner之後main方法執行完畢結束 此時jvm中沒有非Daemon線程 jvm需要退出 jvm中的所有Daemon線程立即終止
在構建Daemon線程時 不能依靠finally中的內容來確保執行關閉或清理資源的邏輯
線程中斷
public static void main(String[] args) throws InterruptedException {
Thread busyThread = new Thread(new BusyRunner(),"busythread");
busyThread.setDaemon(true);
Thread sleepThread = new Thread(new SleepRunner(),"sleeprunner");
sleepThread.setDaemon(true);
busyThread.start();
sleepThread.start();
TimeUnit.SECONDS.sleep(6);
busyThread.interrupt();
sleepThread.interrupt();
System.out.println("busythread isinterrupe is :" + busyThread.isInterrupted());
System.out.println("sleepThread isinterrupe is :" + sleepThread.isInterrupted());
TimeUnit.SECONDS.sleep(6);
}
static class SleepRunner implements Runnable {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class BusyRunner implements Runnable {
@Override
public void run() {
while (true){
}
}
}
知識:
java中聲明拋出InterruptedException的方法 這些方法在拋出InterruptException之前java虛擬機會先將該線程中的中斷標示位清除 然後拋出異常 此時調用isinterrupted 方法將會返回false