一、直接使用 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(密碼)
這種方式瞭解一下即可。對於生產環境一般沒有權限訪問的。