java多執行緒之守護執行緒Daemon()和Join()介紹
最近看了些多執行緒相關的同樣的避免忘了:
我們先模擬一個需求,在http請求的時候我們都會發心跳包,就會一遍又一遍的去檢查心跳是否存在,但是當這個請求不用的時候我們採取什麼方式來把它關閉掉呢?
因為Stop的方法我們已經被java淘汰掉了.這時候我們可以拿守護執行緒來做著件事:
public static void main(String[] args) { Thread t = new Thread(() -> { //啟動一個執行緒 Thread innerThread = new Thread(() -> { //相當於心跳包 try { while(true) { System.out.println("Do some thing for health check."); Thread.sleep(1_00000); //我們假設這是在發心跳包給連結 } } catch (InterruptedException e) { e.printStackTrace(); } }); innerThread.setDaemon(true);//守護執行緒是T,Daemon必須寫在start前面 innerThread.start();//try { Thread.sleep(1_000); System.out.println("T thread finish done.");//T執行緒做的事情 } catch (InterruptedException e) { e.printStackTrace(); } }); t.setDaemon(true); 守護執行緒是main t.start(); }
先捋一捋上面的關係:
main--->裡面有T這個執行緒,---->裡面又包含--->InnerThread 這個執行緒
也就是說 --->main函式一旦停止--->T函式也停止----->T函式一旦停止---->InnerThread執行緒也就停止
這就叫做守護執行緒,
回到上面的例子:也就是說T函式相當於一個連結,innerTheread是心跳包,當這個T連結停止的時候,Innder也就停止心跳包的傳送.
Join()方法介紹 :
上面的圖簡單說一下需求:也就是說我們是用來採集資料的,分別用了4個執行緒,最後把結果都寫到machines表中,但是這裡面沒一個執行緒花的時間都不一樣,所以就需要Join來寫:
Join把指定的執行緒加入到當前執行緒,可以將兩個交替執行的執行緒合併為順序執行的執行緒。
比如線上程B中呼叫了執行緒A的Join()方法,直到執行緒A執行完畢後,才會繼續執行執行緒B。
t.join(); //呼叫join方法,等待執行緒t執行完畢
t.join(1000); //等待 t 執行緒,等待時間是1000毫秒。
模擬上面的需求:
public static void main(String[] args) throws InterruptedException { long startTimestamp = System.currentTimeMillis();//採集開始時間 //模擬多個執行緒去訪問資料庫 Thread t1 = new Thread(new CaptureRunnable("M1", 10000L));//需要花費這麼多時間 Thread t2 = new Thread(new CaptureRunnable("M2", 30000L)); Thread t3 = new Thread(new CaptureRunnable("M3", 15000L)); t1.start();//啟動各個執行緒 t2.start(); t3.start(); t1.join(); t2.join(); t3.join(); long endTimestamp = System.currentTimeMillis();//採集結束時間 System.out.printf("Save data begin timestamp is:%s, end timestamp is:%s\n", startTimestamp, endTimestamp); } } class CaptureRunnable implements Runnable { private String machineName;//名稱 private long spendTime;//花費的時間 public CaptureRunnable(String machineName, long spendTime) { this.machineName = machineName; this.spendTime = spendTime; } @Override public void run() { //do the really capture data. try { Thread.sleep(spendTime);//需要費時這麼長時間 System.out.printf(machineName + " completed data capture at timestamp [%s] and successfully.\n", System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } public String getResult() { return machineName + " finish."; } }
結果:
M1 completed data capture at timestamp [1521545947051] and successfully.
M3 completed data capture at timestamp [1521545952051] and successfully.
M2 completed data capture at timestamp [1521545967051] and successfully.
Save data begin timestamp is:1521545937048, end timestamp is:1521545967051
比如線上程B中呼叫了執行緒A的Join()方法,直到執行緒A執行完畢後,才會繼續執行執行緒B。
我們看到結果:
也就是說他們在等其他執行緒結束