Java併發(三)----創建線程的三種方式及查看進程線程

一、直接使用 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(密碼)

這種方式瞭解一下即可。對於生產環境一般沒有權限訪問的。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章