idea以任意順序debug多執行緒程式
@
目錄在idea中使用debug可以讓多個執行緒以任意順序執行,先介紹一下基礎知識,然後介紹具體做法。
1 debug 兩類 Supspend
在斷點處右鍵,可以看到Suspend分兩類,一類是All,一類是Thread。當某個執行緒到達斷點處會觸發Suspend,All會使得所有執行緒都暫停,Thread只會使當前觸發的執行緒暫停,其他執行緒不受影響。
在idea中使用debug可以讓多個執行緒以任意順序執行,先介紹一下基礎知識,然後介紹具體做法。
以下面的程式碼為例,有3個MyThread執行緒以及一個主執行緒main。3個執行緒分別睡眠 1/2/3 秒,主執行緒睡眠 5 秒。下面分三種情況檢視結果:
- 正常執行,執行完的順序為 1, 2, 3, main
- 在斷點1處打斷點,設定為 All,線上程1觸發後所有執行緒均暫停,可以通過Resume繼續執行下一個斷點,正常情況應該是3次Resume才能結束,但在有些時候idea會提示 skipped breakpoint at because it happened inside debugger evaluation,會跳過一些斷點,這可能是ide本身的問題,可以在Settings->Build ... ->Debugger->Data Views->Java中 取消 Enable 'toString()' object view。
- 在斷點1處打斷點,設定為 Thread,3個子執行緒都會在斷點處暫停,main執行緒沒有暫停,會先執行完。
package org.example; public class Test{ public static void main(String arg[]){ MyThread thread1 = new MyThread(1); MyThread thread2 = new MyThread(2); MyThread thread3 = new MyThread(3); thread1.setName("Thread 1"); thread2.setName("Thread 2"); thread3.setName("Thread 3"); thread1.start(); thread2.start(); thread3.start(); try { Thread.sleep(1000*5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("主執行緒完成"); } private static class MyThread extends Thread { private int num; public MyThread(int num) { this.num = num; } @Override public void run() { String name = Thread.currentThread().getName(); try { Thread.sleep(1000*num); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"斷點1"); //斷點1 System.out.println(Thread.currentThread().getName()+"斷點之間執行"); System.out.println(Thread.currentThread().getName()+"斷點2"); //斷點2 } }
2 按照順序執行執行緒
在子執行緒打兩個Thread斷點,通過Frames控制子執行緒的執行順序,假設斷點之間的執行順序為3, 2, 1, 2, 1, 3。其中第一次執行從斷點1開始,執行到斷點2之前,第二次執行會執行斷點2並結束。
如果感覺不好理解,可以將MyThread換成三個不同的類分別對應三個執行緒,在三個類中分別打斷點。這裡我不再替換。
debug執行,稍等一會,三個執行緒都會到第一個斷點停下,此時未有任何輸出,注意在左下角Frames的選單,點開,會發現三個執行緒都在Frames內,這說明三個執行緒都已經暫停,有時候下拉框會有main,但其實main不會暫停。
想先執行Thread 3,則在下拉框選擇Thread 3,點一下Resume,此時Thread 3的第一個斷點和斷點之間的程式碼執行,Thread 3暫停在第二個斷點上,其他暫停的執行緒不受影響。
對應的後續執行順序是,切換到Thread 2/1/2/1/3,每次切換都Resume一次。
總結:想讓哪個執行緒先執行就在下拉框切換到相應的執行緒,並Resume,則該執行緒執行到下一個斷點,如果沒有下一個斷點則會一直執行直到結束。此時,其他暫停的執行緒會一直暫停等待。
這樣的做法可以推廣到多個執行緒,對於需要暫停的執行緒都打上斷點即可,每個執行緒可以打多個,方便控制執行順序。對於不需要暫停的執行緒可以不打斷點,就像這裡的main執行緒一樣。
3 Condition的使用
另外如果只想讓某個執行緒在斷點處停止,可以使用斷點的Condition,如上面的程式碼中只想讓第一個執行緒暫停,則可以在斷點處右鍵,在Condition中填入Thread.currentThread().getName().equals("Thread 1");