一、直接使用 Thread
// 建立執行緒物件
Thread t = new Thread() {
public void run() {
// 要執行的任務
}
};
// 啟動執行緒
t.start();
例如:
// 構造方法的引數是給執行緒指定名字,推薦
Thread t1 = new Thread("t1") {
@Override
// run 方法內實現了要執行的任務
public void run() {
log.debug("hello");
}
};
t1.start();
輸出
19:19:00 [t1] c.ThreadStarter - hello
注意:這裡透過@Slf4j
二、使用 Runnable
把【執行緒】和【任務】(要執行的程式碼)分開
-
Thread 代表執行緒
-
Runnable 可執行的任務(執行緒要執行的程式碼)
Runnable runnable = new Runnable() {
public void run(){
// 要執行的任務
}
};
// 建立執行緒物件
Thread t = new Thread( runnable );
// 啟動執行緒
t.start();
例如:
// 建立任務物件
Runnable task2 = new Runnable() {
@Override
public void run() {
log.debug("hello");
}
};
// 引數1 是任務物件; 引數2 是執行緒名字,推薦
Thread t2 = new Thread(task2, "t2");
t2.start();
輸出
19:19:00 [t2] c.ThreadStarter - hello
Java 8 以後可以使用 lambda 精簡程式碼
// 建立任務物件
Runnable task2 = () -> log.debug("hello");
// 引數1 是任務物件; 引數2 是執行緒名字,推薦
Thread t2 = new Thread(task2, "t2");
t2.start();
小結
-
方法1 是把執行緒和任務合併在了一起,方法2 是把執行緒和任務分開了
-
推薦使用用 Runnable,因為 更容易與執行緒池等高階 API 配合
-
用 Runnable 讓任務類脫離了 Thread 繼承體系,更靈活
三、FutureTask
FutureTask (未來任務)能夠接收 Callable 型別的引數,用來處理有返回結果的情況
// 建立任務物件
FutureTask<Integer> task3 = new FutureTask<>(() -> {
log.debug("hello");
Thread.sleep(2000);
return 100;
});
// 引數1 是任務物件; 引數2 是執行緒名字,推薦
new Thread(task3, "t3").start();
// 執行到這裡主執行緒阻塞,會同步等待 task 執行完畢的結果
Integer result = task3.get();
log.debug("結果是:{}", result);
輸出
19:22:27 [t3] c.ThreadStarter - hello
19:22:29 [main] c.ThreadStarter - 結果是:100
可以看到兩秒後主執行緒返回結果
四、觀察多個執行緒同時執行
主要是理解
-
交替執行
-
誰先誰後,執行緒的執行不由我們控制
程式碼
public static void main(String[] args) {
new Thread(() -> {
while(true) {
log.debug("running");
}
},"t1").start();
new Thread(() -> {
while(true) {
log.debug("running");
}
},"t2").start();
}
結果
可以看到,執行緒是交替執行的。但是誰先誰後不是我們控制的。但是如果是單核CPU的話執行這段程式的話,只會有一個執行緒開始執行。
五、檢視程式執行緒
5.1 windows
-
工作管理員可以檢視程式和執行緒數,也可以用來殺死程式
-
控制檯
tasklist
檢視程式 -
控制檯
taskkill /F /PID pid編號
殺死程式
5.2 linux
-
ps -fe
檢視所有程式 -
ps -fe | grep 關鍵詞
檢視所有程式 -
ps -fT -p <PID>
檢視某個程式(PID)的所有執行緒 -
kill
殺死程式 -
top
按大寫 H 切換是否顯示執行緒 -
top -H -p <PID>
檢視某個程式(PID)的所有執行緒,可持續檢視執行緒的狀態
5.3 Java
-
jps
命令檢視所有 Java 程式 -
jstack <PID>
檢視某個 Java 程式(PID)的所有執行緒狀態 ,只能檢視某一刻某個程式所有執行緒較詳細的狀態 -
jconsole
來檢視某個 Java 程式中執行緒的執行情況(圖形介面) - 如果是從命令列啟動,使 JDK 在 PATH 上,執行 jconsole 即可;如果從 GUI shell 啟動,找到 JDK 安裝路徑,開啟 bin 資料夾,雙擊 jconsole
jconsole 遠端監控配置
-
需要以如下方式執行你的 java 類
java -Djava.rmi.server.hostname=`ip地址` -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=`連線埠` -Dcom.sun.management.jmxremote.ssl=是否安全連線 -Dcom.sun.management.jmxremote.authenticate=是否認證 java類
-
修改 /etc/hosts 檔案將 127.0.0.1 對映至主機名
如果要認證訪問,還需要做如下步驟
-
複製 jmxremote.password 檔案
-
修改 jmxremote.password 和 jmxremote.access 檔案的許可權為 600 即檔案所有者可讀寫
-
連線時填入 controlRole(使用者名稱),R&D(密碼)
這種方式瞭解一下即可。對於生產環境一般沒有許可權訪問的。