国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
歡迎光臨貓小專區(qū)

第五章線程與異常處理(上)

上一章我們介紹了Java的面向?qū)ο蟮臋C制:類、包和接口。本章我們將介紹一下Java的另外兩個機制:多線程(Multithread)和異常處理(Exception)。本章前半部分是關(guān)于Thread這一基本類以及一套先進的同步原語的介紹,它們使得利用Java編寫多線程大為方便。在本章的后半部分我們將介紹Java的異常處理機制(Exception),異常處理機制提高了程序的健壯性。另外,本章中間將介紹一個Java的debugger工具Jdb的使用,Jdb工具對于調(diào)試多線程程序尤其有好處。

5.1 多線程(Multithread)

  5.1.1 線程的基本概念

在介紹多線程之前,我們先來了解一些相關(guān)的基本概念。一般來說,我們把程序的一次執(zhí)行稱為進程(process)。一個進程包括一個程序模塊和該模塊一次執(zhí)行時所處理的數(shù)據(jù)。每個進程與其它進程擁有不同的數(shù)據(jù)塊,其內(nèi)存地址是分開的。進程之間的通信要通過尋址,一般需使用信號、管道等進行通信。線程(thread)是指進程內(nèi)部一段可獨立執(zhí)行的有獨立控制流的指令序列。子線程與其父線程共享一個地址空間,同一個任務(wù)中的不同線程共享任務(wù)的各項資源。
多進程與多線程是多任務(wù)的兩種類型。以前的操作系統(tǒng),如Win31,只運行多進程,而Win95及WinNT則支持多線程與多進程。Java通過提供Package類(Java.lang.package)支持多進程,而提供Thread類來支持多線程。
多線程與多進程的主要區(qū)別在于,線程是一個進程中一段獨立的控制流,一個進程可以擁有若干個線程。在多進程設(shè)計中各個進程之間的數(shù)據(jù)塊是相互獨立的,一般彼此不影響,要通過信號、管道等進行交流。而在多線程設(shè)計中,各個線程不一定獨立,同一任務(wù)中的各個線程共享程序段、數(shù)據(jù)段等資源,如圖5.1。
正如字面上所表述的那樣,多線程就是同時有多個線程在執(zhí)行。在多CPU的計算機中,多線程的實現(xiàn)是真正的物理上的同時執(zhí)行。而對于單CPU的計算機而言,實現(xiàn)的只是邏輯上的同時執(zhí)行。在每個時刻,真正執(zhí)行的只有一個線程,由操作系統(tǒng)進行線程管理調(diào)度,但由于CPU的速度很快,讓人感到像是多個線程在同時執(zhí)行。
多線程比多進程更方便于共享資源,而Java又提供了一套先進的同步原語解決線程之間的同步問題,使得多線程設(shè)計更易發(fā)揮作用。用Java設(shè)計動畫以及設(shè)計多媒體應(yīng)用實例時會廣泛地使用到多線程,在后面幾章你將看到多線程的巨大作用,當(dāng)然,現(xiàn)在必須先學(xué)習(xí)一些多線程的基本知識,慢慢地你就體會到它的優(yōu)越性。

  5.1.2 線程的狀態(tài)

  如同進程有等待、運行、就緒等狀態(tài)一樣,線程也有其狀態(tài)。
當(dāng)一個線程通過new被創(chuàng)建但還未運行時,稱此線程處于準(zhǔn)備狀態(tài)(new狀態(tài))。當(dāng)線程調(diào)用了start()方法或執(zhí)行run()方法后,則線程處于可運行狀態(tài)。若在等待與其它線程共享資源,則稱線程處于等待狀態(tài)。線程的另一個狀態(tài)稱為不可運行(notrunnable)狀態(tài),此時線程不僅等分享處理器資源,而且在等待某個能使它返回可運行狀態(tài)的事件,例如被方法suspend()掛起的進程就要等待方法resume()方可被喚醒。當(dāng)調(diào)用了stop()方法或線程執(zhí)行完畢,則線程進入死亡(dead)狀態(tài)。線程的各個狀態(tài)之間的轉(zhuǎn)換關(guān)系見圖5.2。

  5.1.3 創(chuàng)建線程

  在了解基本概念后,下面學(xué)習(xí)如何在Java中創(chuàng)建多線程。
Java通過java.lang.Thread類來支持多線程。在Thread類中封裝了獨立的有關(guān)線程執(zhí)行的數(shù)據(jù)和方法,并將多線程與面向?qū)ο蟮慕Y(jié)構(gòu)合為一體。
Java提供了兩種方法創(chuàng)建線程,一種是繼承Thread類,另一種則是實現(xiàn)接口Runnable。
1.繼承Thread類
通過繼承Thread類創(chuàng)建線程十分簡單,只需要重載run()方法提供執(zhí)行入口就可以,下面我們通過例5.1來解釋說明。
例5.1 ThreadTest1.java。

  1. import java.lang.Thread;
  2. import java.lang.System;
  3. import java.lang.Math;
  4. import java.lang.InterruptedException;
  5. class ThreadTest1{
  6. public static void main(String args[])
  7.   throws java.io.IOException{
  8.   System.out.println("If want to show the result,press return");
  9.   MyThread thread1=new MyThread("thread1");
  10.   MyThread thread1=new MyThread("thread2");//創(chuàng)建了兩個線程thread1和thread2
  11.   thread1.start();//開始執(zhí)行線程
  12.   thread2.start();
  13.   char ch;
  14.   while((ch=(char)System.in.read()) != ‘\n‘);//不斷循環(huán),等待輸入回車符
  15.   thread1.tStart();//改變thread1和thread2中的循環(huán)控制變量的值
  16.   thread2.tStart();//以下部分保證main()方法是最后一個結(jié)束的
  17.   while((thread1.isAlive())|(thread2.isAlive()));
  18.   /*{
  19.   you can do anything that you want to do here.
  20.   }
  21.   */
  22.   System.out.println("The test is end.");
  23. }
  24. }
  25. //類MyThread繼承了類Thread
  26. class MyThread extends Thread{
  27. private boolean keepRunning=true;
  28. public MyThread(String id){//類MyThread的構(gòu)造方法
  29.   super(id);
  30. }
  31. void randomWait(){//讓線程處于等待狀態(tài)
  32.   try{
  33.     sleep((long)(3000*Math.random()));
  34.   }
  35.   catch(InterruptedException x){
  36.     System.out.println("Interrupted!");
  37.   }
  38. }
  39. public void tStart(){
  40.   keepRunning=false;
  41. }
  42. public void run(){//重寫了類Thread中的方法run(),main()中調(diào)用Thread的方法start()后將自動調(diào)用此方法
  43. int i=0;
  44. while(keepRunning) i++;//i代表循環(huán)次數(shù)
  45. //輸出結(jié)果
  46. for(int j=0;j<=3;i++){
  47.   randomWait();
  48.   System.out.println("I am"+getName()+"—— I have run"+i+"times.");
  49.   i++;
  50.   }
  51.   System.out.println(getName()+" is dead!");
  52. }
  53. }
  54.  
這個程序中創(chuàng)建了兩個線程thread1和trhrad2。每個線程將打印一些內(nèi)容。當(dāng)線程死亡時,將打印出線程死亡信息。試著執(zhí)行一下這個程序,你將發(fā)現(xiàn)每次的結(jié)果都不盡相同。
運行結(jié)果:(略)
下面我們分析一下這個程序。為創(chuàng)建Thread,第一行你必須寫importjava.lang.Thread。行6~25中書寫的類ThreadTest1包含了一個main()方法(行7~24)。行8的throwsjava.io.IOException暗示了main()方法中可以產(chǎn)生IOException(有關(guān)異常處理后面幾節(jié)將詳細介紹),這主要是為了調(diào)用方法System.in.read()實現(xiàn)輸入功能。main()方法中創(chuàng)建了兩個MyThread的對象,即行10的thread1與行11的thread2。
行28~55中書寫的類MyThread是Thread類的子類。在類MyThread中重寫了方法run()(行43~54)。在此種構(gòu)造線程的方法中,這是必須的。行29~33定義了MyThread類的構(gòu)造方法MyThread(Stringid)。行32和行40定義了方法randomWait()和tStart()。
在ThreadTest1的main()方法中,當(dāng)行13調(diào)用thread1.start()與thread2.start()后,線程thread1與thread2進入可運行狀態(tài),分別自動執(zhí)行其run()方法,而main()方法也繼續(xù)執(zhí)行,此時相當(dāng)于有三個線程在同時執(zhí)行。
看一下程序,此時thread1與thread2在執(zhí)行第44~54行的run()方法,為斷循環(huán)并累計循環(huán)次數(shù),而main()則在等待循環(huán)直至入為回車符。輸入回車符,main()方法結(jié)束循環(huán),繼續(xù)執(zhí)行,調(diào)用了MyThread中方法tStart()(41~43行),這樣結(jié)束了Thread1與Thread2在run()方法中的循環(huán),開始執(zhí)行輸出。由于thread1,thread2與main()三個線程輪流占有CPU,所以顯示了各自結(jié)果,這也是為何多次執(zhí)行結(jié)果不同的原因,此時體現(xiàn)了多線程的功能。
請注意一下Run()中調(diào)用了MyThread類中自定義的方法randomWait()(33~40行)。在randomWait()中調(diào)用了方法sleep(),sleep()方法是Thread類中的方法,它讓正在執(zhí)行的線程小睡片刻,進入不可運行狀態(tài)(notrunnable狀態(tài)),當(dāng)時間到時,線程會回復(fù)到runnable狀態(tài)。當(dāng)線程執(zhí)行sleep()時,有可能會被打斷,因而程序中加了一段處理InterruptedException的中斷處理和打印信息,這樣加強了程序的健壯性。
另外,人們會注意到,在main()中有一段循環(huán)并未完成什么功能,這是為了簡化程序,其實那段時間中你可以做你想完成的任何工作。但請注意,在執(zhí)行時,最后一個結(jié)束的必須是main()方法,而不可以是其它,否則執(zhí)行結(jié)束將不返回C:提示符,這也是在程序中為何調(diào)用了isAlive()方法進行判別的原因。調(diào)用類Thread的isAlive()方法可以測試線程是否仍在運行狀態(tài)(此外指還未死亡)。
至此,你已真正了解了你的第一個關(guān)于Thread的程序,其實Thread中還有很多方法在此未被使用,后面將會進一步介紹。下面先介紹一下創(chuàng)建Thtead的另一個方法:利用實現(xiàn)接口Runnable創(chuàng)建Thread。
2.實現(xiàn)接口Runnable
使用用類java.lang.Runnable中的接口Runnable也可創(chuàng)建線程。下面的例子與例5.1實現(xiàn)的功能相同,只是它利用接口Runnable來實現(xiàn)。
例5.2 ThreadTest2.java。
  1. import java.lang.Thread;
  2. import java.lang.System;
  3. import java.lang.Math;
  4. import java.lang.InterruptedException;
  5. import java.lang.Runnable;
  6. class ThreadTest2{
  7. public static void main(String args[])
  8.   throws java.io.IOException{
  9.   System.out.println("If want to show the result,press return");//創(chuàng)建了兩個MyClass類的對象//class1和class2,MyClass類實現(xiàn)了接口Runnable
  10.   MyClass class1 = new MyClass("thread1");
  11.   MyClass class2 = new MyClass("thread2");//創(chuàng)建了兩個MyClass類的對象class1和class2,MyClass類實現(xiàn)了接口Runnable
  12.   Thread thread1=new Thread(class1);
  13.   Thread thread2=new Thread(class2);//將對象class1和class2作為參數(shù)傳給Thread類的構(gòu)造函數(shù),創(chuàng)建了兩個線程thread1和thread2。
  14.   thread1.start();//開始執(zhí)行線程
  15.   thread2.start();
  16.   char ch;
  17.   while((ch=(char)System.in.read()) != ‘\n‘);//不斷循環(huán),等待輸入回車符
  18.   class1.tStart();//改變thread1和thread2中的循環(huán)控制變量的值
  19.   class2.tStart();//以下部分保證main()方法是最后一個結(jié)束的
  20.   while((thread1.isAlive())||(thread2.isAlive()));
  21.   /*{
  22.   you can do anything that you want to do here.
  23.   }
  24.   */
  25.   System.out.println("The test is end.");
  26. }
  27. }
  28. //類MyClass實現(xiàn)了接口Runnable
  29. class MyClass implements Runnable{
  30. boolean keepRunning=true;
  31. String name;
  32. public MyClass(String id){//類MyClass的構(gòu)造方法
  33.   name=id;
  34. }
  35. void randomWait(){//讓線程處于等待狀態(tài)
  36.   try{
  37. Thread.currentThread().sleep((long)(3000*Math.random()));//注意:接口 Runnable中沒有方法sleep(),所以必須先調(diào)用Thread的類方法currentThread()來獲取一個Thread的對象,然后再調(diào) 用方法seleep()
  38.   }
  39.   catch(InterruptedException x){
  40.     System.out.println("Interrupted!");
  41.   }
  42. }
  43. public void tStart(){
  44.   keepRunning=false;
  45. }
  46. public void run(){//與程序ThreadTest1.java類似
  47. int i=0;
  48. while(keepRunning) i++;//i代表循環(huán)次數(shù)
  49. //輸出結(jié)果
  50. for(int j=0;j<=3;j++){
  51.   randomWait();
  52.   System.out.println("I am "+name+"—— I have run "+i+" times.");
  53.   i++;
  54.   }
  55.   System.out.println(name+" is dead!");
  56. }
  57. }
  58.  

 

 

  運行結(jié)果:(略)
ThreadTest2創(chuàng)建thread1與thread2的方法(11~14行)與ThreadTest1不同,ThreadTest2直接創(chuàng)建了一個Thread的對象,并將Myclass的對象作為參數(shù)傳給Thread的構(gòu)造方法。任何實現(xiàn)了Runnable接口的類的對象都可以作Thread構(gòu)造方法的參數(shù)。在main()方法中,其余部分程序ThreadTest2與ThreadTest1.java相同。
ThreadTest2的MyClass類(31~59行)實現(xiàn)了接口Runnable,注意MyClass的構(gòu)造方法實現(xiàn)了name這一類變量,實現(xiàn)run()時不需要調(diào)用Thread的方法getName(),但在實現(xiàn)randomWait()時要使用Thread.currentThread().Sleep()(39行),因為Runnable接口并未提供方法sleep(),因而實現(xiàn)時必須調(diào)用Thread的類方法currentThread()來調(diào)用sleep()。
事實上,無論用繼承Thread的方法或用實現(xiàn)接口Runnable的方法來實現(xiàn)多線程,在程序書寫時區(qū)別不大,只需概念清楚略加注意便可。使用繼承Thread類的方法比較簡單易懂,實現(xiàn)方便。但如果你創(chuàng)建的Thread需要是某個其它類的子類時,使用繼承Thread的方法就會出麻煩。比如,實現(xiàn)Applet時,每個applet必須是java.applet.Applet的子類,此時想要實現(xiàn)多線程,只有通過使用Runnable接口,當(dāng)然,使用Runnable接口來實現(xiàn)線程,在書寫時會比較麻煩,因為你將不得不多做一些工作才可調(diào)用Thread的方法。
3.線程同步
在使用多線程時,由于可以共享資源,有時就會發(fā)生沖突。舉一個簡單的例子,有兩個線程thread1負責(zé)寫,thread2負責(zé)讀,當(dāng)它們操作同一個對象時,會發(fā)現(xiàn)由于thread1與thread2是同時執(zhí)行的,因此可能thread1修改了數(shù)據(jù)而thread2讀出的仍為舊數(shù)據(jù),此時用戶將無法獲得預(yù)期的結(jié)果。問題之所以產(chǎn)生主要是由于資源使用協(xié)調(diào)不當(dāng)(不同步)造成的。以前,這個問題一般由操作系統(tǒng)解決,而Java提供了自己協(xié)調(diào)資源的方法。
Java提供了同步方法和同步狀態(tài)來協(xié)調(diào)資源。Java規(guī)定:被宣布為同步(使用Synchronized關(guān)鍵字)的方法,對象或類數(shù)據(jù),在任何一個時刻只能被一個線程使用。通過這種方式使資源合理使用,達到線程同步的目的。
我們將程序5.1的類MyThread中的方法run()改成如下所示(見程序片段5.3),并加入一個類SynchronizedShow實現(xiàn)同步,大家可以運行看到執(zhí)行結(jié)果:每次執(zhí)行Show()的只有一個線程。
例5.3 ThreadTest3.java片段
public void run(){
int i=0;
while(keepRunning) i++;//i代表循環(huán)次數(shù)
//輸出結(jié)果
SynchronizedShow.show(getName(),i);
SynchronizedShow.println(getName()+"isdead!");
}
class SychronizedShow{
//方法show(String,int)被宣布為同步的方法,因此每次只有一個線程能調(diào)用這個方法
public static synchronized voidshow(String,name,int i){
int k;
k=i;
for(intj=0;j<=3;j++){
MyThread t=(Mythread)Thread.currentThread();
t.randomWait();
System.out.println("Iam"+name+"—— I haverun"+k+" times.");
k++;
}
}
}
運行結(jié)果(略)
另外,利用Synchronized可以鎖定對象。
例如:Synchronized(某個對象A){
//程序塊
}
在此程序塊中,對于相同的對象A,在任何時候只可以有一個線程在此代碼中執(zhí)行,但對于不同的對象還是有很多個線程同時執(zhí)行的。用同樣的方法也可以協(xié)調(diào)類數(shù)據(jù),例如:
Synchroinzed(new欲鎖定的類().getmethod()){
//程序塊
}
方法getmethod()是用來獲取類數(shù)據(jù)的,這樣通過利用Synchronized這一關(guān)鍵字,我們可以自由協(xié)調(diào)對象實體的各種數(shù)據(jù)。
除了簡單使用Synchronized這一關(guān)鍵字外,Java有一套復(fù)雜的同步機制,其基本原理采用了C.A.R.Hoare提出的,并已被廣泛使用的監(jiān)視規(guī)則和條件變量規(guī)則。在Java中,所有的類與對象都和管程(monitor)聯(lián)系在一起。當(dāng)一個對象獲得管程(monitor)時,它就可以執(zhí)行同步方法,直至它讓出管程(monitor),其它對象方可進入同步方法。當(dāng)一個方法被完成時,它將自動讓管理(monitor),另外執(zhí)行某些方法例如wait(),suspend()等時也會讓出管程(monitor)。
讀者可以試著將例5.1的main()方法改成以下形式(風(fēng)險5.4)執(zhí)行一下。人們會發(fā)現(xiàn)與前面利用Synchronized的結(jié)果類似,原因是thread1執(zhí)行suspend()后被掛起直至resume()方被喚醒。因此用這種方法也可以實現(xiàn)同步。
例5.4 Thread Test4.java的程序片斷。
public static void main(String args[])
throws java.io.IOException{
System.out.println("If want toshow the result,press return");
MyThread thread1=newMyThread("thread1");
MyThread thread2=newMyThread("thread2");
thread1.start();
thread2.start();
char ch;
while((ch=(char)System.in.read())!=‘\n‘);
thread1.tStart();
//將線程thread1掛起
thread1.suspend();
thread2.tStart();
while(thread2.isAlive());
//線程thread2進入死亡狀態(tài)后,釋放線程thread1
thread1.resume();
while(thread1.isAlive());
/*{
you can do anything that youwant to do here.
}
*/
System.out.println("The testis end.");
}
運行結(jié)果:(略)
4.進一步學(xué)習(xí)
上幾節(jié)我們學(xué)習(xí)了定義Thread的兩種方法,線程的同步的基本知識。在本節(jié)中我們將進一步給出有關(guān)線程的一些更詳細的內(nèi)容。
(1)若干常用的方法
首先,我們給出一些Thread類中最常用的方法供大學(xué)參考。
■currentThread()
這是一個類方法,返回當(dāng)前正在執(zhí)行的線程。
■isAlive()
判別一個線程是否仍然活著,包括這個線程正在執(zhí)行或有機會被執(zhí)行。返回一個布爾值。
■suspend()
懸掛起某個線程,并使得這個線程只可被resume()方法激活。
■resume()
與suspend()配合使用。喚醒線程。
■yeild()
強迫線程交出執(zhí)行權(quán)利供其它線程使用。
■stop()
使線程進入死亡(dead)狀態(tài)。
這些方法是線程中最常被使用到的方法,若要詳細了解更多的內(nèi)容可以查閱Java的API。
(2)線程優(yōu)先級與調(diào)度
由于我我們一般使用的計算機是單CPU的,所以在執(zhí)行多線程程序時需進行線程調(diào)度。線程調(diào)度是由線程的優(yōu)先級決定的。高優(yōu)先級的線程總是先運行的。Java采用的是搶占式(preemptive)的調(diào)度方式,即當(dāng)高優(yōu)先級的線程進入可運行(runnable)狀態(tài)時,會搶占低優(yōu)先級的線程的位置,并開始執(zhí)行。當(dāng)同時有兩個或兩個以上的線程具有高優(yōu)先級并進入可運行狀態(tài),Java的調(diào)度會自動在這些線程間交替調(diào)度執(zhí)行。
在Java中,Thread類中預(yù)定義了三個常量:
MAX_PRIORITY,MIN_PRIORITY,NORM_PRIORITY,
一個線程的優(yōu)先級應(yīng)在MAX_PRIORITY與MIN_PRIORITY之間。NORM_PRIORITY是缺省的優(yōu)先級值,一般是MIN_PRIORITY與MAX_PRIORITY的平均值。
在Java中,Thread類提供了方法設(shè)置和獲取優(yōu)先級。
setPriority(int)  用于設(shè)置線程的優(yōu)先數(shù)
setPriority()   用于獲取線程的優(yōu)先數(shù)
(3)線程組(Thread Group)
線程組是包括了許多線程的對象集。每個線程有自己特定的線程組。一個線程在創(chuàng)建時就屬于某個線程組,直至其執(zhí)行結(jié)束,此線程不可更改其所屬的線程組。Thread類中提供了構(gòu)造方法使創(chuàng)建線程時同時決定其線程組。Thread類總共提供了六種構(gòu)造方法:
Thread();
Thread(String);
Thread(Runnable);
Thread(Runnable,String);
Thread(ThreadGroup,String);
Thread(ThreadGroup,Runnable,String);
前四種缺省了線程組,表示所創(chuàng)建的線程屬于main線程組,后兩種則指定了所創(chuàng)建的線程的線程組。線程可以訪問自己所在的線程組,但不能訪問本線程組的父類。對線程組進行操作就是對線程組中的各個線程同時進行操作。
線程組的構(gòu)造方法:
ThreadGroup(String groupName)
創(chuàng)建名為groupName的線程組,該線程組的父類為當(dāng)前線程所在程組。
ThreadGroup(ThreadGroup parent,StringgroupName)
創(chuàng)建名為groupName的線程組,該線程組的父類是parent。
(4)wait()和notify()方法
Java在類java.lang.Object中定義了wait()和notify()方法,調(diào)用它們也可以實現(xiàn)線程之間的同步。
■public final void wait(longmillseconds) throws InterruptedException
調(diào)用此方法時,被調(diào)對象進入等待狀態(tài),直到被喚醒或等待時間到。
■public final void notify()
喚醒一個對象內(nèi)處于等待狀態(tài)的對象。
■public find void Allotify()
喚醒一個對象內(nèi)所有處于等待狀態(tài)的對象。

5.2 Debugger的使用

  至此我們已經(jīng)書寫了不少程序,大家可能發(fā)覺出錯要調(diào)試很困難,其實java工具包中的Javadebugger為用戶提供了方便的調(diào)試機制。雖然jdb的界面不是很漂亮,但很有用,尤其對于調(diào)試多線程程序。
Java的debugger需要jdb命令激活。如下執(zhí)行:
C:\>jdb
在執(zhí)行之前,請用帶-g參數(shù)的javac對程序進行編譯,本節(jié)我們使用了前一章中check.java,第一步先重新編譯方法如下:
C:\synetjava\java\exmples>javac -gcheck.java
用下面的方法可以進入jdb,可以直接在jdb后緊接要調(diào)試的類名,也可缺省,在進入jdb后利用load載入要調(diào)試的類。
C:\MyDemo\dawn>jdb Check
Initializing jdb...
0xe8d370:class(Check)
在Check這一類名前的16進制數(shù)是Check類在Java運行時的標(biāo)識。
進入了jdb后,可以使用help來獲取所需的使用信息:
> help
** command list **
run [class [args]]     --start execution of application‘s main class

  threads [threadgroup]   --list threads
thread <thread id>     --set default thread
suspend [thread id(s)]   --suspend threads (default: all)
resume [thread id(s)]   --resume threads (default: all)
where [thread id] | all  -- dump athread‘s stack
wherei [thread id] | all -- dump athread‘s stack, with pc info
up [n frames]       --move up a thread‘s stack
down [n frames]      --move down a thread‘s stack
kill <thread> <expr>   --kill a thread with the given exceptionobject
interrupt <thread>    --interrupt a thread

  print <expr>       --print value of expression
dump <expr>        --print all object information
eval <expr>        --evaluate expression (same as print)
set <lvalue> = <expr>   --assign new value to field/variable/arrayelement
locals           --print all local variables in current stackframe

  classes          --list currently known classes
class <class id>     --show details of named class
methods <class id>    --list a class‘s methods
fields <class id>    --list a class‘s fields

  threadgroups       --list threadgroups
threadgroup <name>    --set current threadgroup

  stop in <classid>.<method>[(argument_type,...)]
--set a breakpoint in a method
stop at <class id>:<line>-- set a breakpoint at a line
clear <classid>.<method>[(argument_type,...)]
--clear a breakpoint in a method
clear <class id>:<line> --clear a breakpoint at a line
clear          --list breakpoints
catch <class id>    --break when specified exception thrown
ignore <class id>    --cancel ‘catch‘ for the specified exception
watch [access|all] <classid>.<field name>
--watch access/modifications to a field
unwatch [access|all] <classid>.<field name>
--discontinue watching access/modifications toa field
trace methods [thread] -- trace methodentry and exit
untrace methods [thread] -- stoptracing method entry and exit
step           --execute current line
step up         --execute until the current method returns toits cal
ler
stepi          --execute current instruction
next           --step one line (step OVER calls)
cont           --continue execution from breakpoint

  list [line number|method] -- printsource code
use (or sourcepath) [source file path]
--display or change the source path
exclude [class id ... |"none"]
--do not report step or method events forspecified classes
classpath -- print classpath info fromtarget VM

  monitor <command>   --execute command each time the program stops
monitor        -- listmonitors
unmonitor <monitor#>  --delete a monitor
read <filename>    --read and execute a command file

  lock <expr>      --print lock info for an object
threadlocks [thread id] -- print lockinfo for a thread

  disablegc <expr>    --prevent garbage collection of an object
enablegc <expr>     --permit garbage collection of an object

  !!            --repeat last command
<n> <command>      --repeat command n times
help (or ?)       --list commands
version         --print version information
exit (or quit)      --exit debugger

  <class id>: full class namewith package qualifiers or a
pattern with a leading or trailingwildcard (‘*‘).
<thread id>: thread number asreported in the ‘threads‘ command
<expr>: a Java(tm) ProgrammingLanguage expression.
Most common syntax is supported.

  Startup commands can be placed ineither "jdb.ini" or".jdbrc"
in user.home or user.dir
>
利用命令stop in <classid>.<method>可以在方法中設(shè)置斷點,用命令run運行方法。
>stop in Check.main
Breakpoint set Check.main
>run Check
running...
main[1]
Breakpoint hit: Check.main(Chech:18)
main[1] list
14   }
15  }
16  class Check{
17   public static voidmain(String args[]]){
18  =>  Son s=new Son();
19     s.speak();
20   }
21   }
main[1]
=>所指的地方即為斷點處,然后使用step命令進行步調(diào)執(zhí)行,結(jié)果提示斷點設(shè)置到了類son中用list顯示,就可以清楚地看到斷點所在位置。
main[1]step
main[1]
Breakpoint hit:Son.<init>(Son:9)
main[1]list
5    void speak(String s){
6      System.out.println("Ilike "+s+".");
7    }
8   }
9   =>class Son extendsFather{
10   void speak(){
11      System.out.println("Myfather sys:");
12      super.speak();
13      super.speak("hunting");
用cont命令可以繼續(xù)執(zhí)行下去,本例十分簡單,所以立即給出了運行結(jié)果。我們還可以試一試help中顯示的其它命令,methodscheck顯示了check類中定義的方法,memory顯示了java運行時刻提供的內(nèi)存等等,用戶可以自己去試用一下。
main[1]cont
My father syas:main[1]
I am Father.
I like hunting.
//顯示check類中定義的方法
main[1]methods Check
void main(String[])
void <init>()
//顯示java運行時刻提供的內(nèi)存main[1]memory
Free:295928,total:1777656
//列出線程組
main[1]threadgrouts
1.(java.lang.ThreadGroup)0xe600b8system
2.(java.lang.ThreadGroup)0xe655e0 main
3.(java.lang.ThreadGroup)0xe8ddd8Check.main
//列出指定線程組中的線程
main[1]threads system
Group system:
1.(java.lang.Thread)0xe600d0  Frinalizertherad suspended
2.(java.lang.Thread)0xe65570  Debuggeragent running
3.(sun.tools.debug.BreakpointHandler)0xe8b080Breakpoint handler cond. waitin
Group main:
4.(java.lang.Thread)0xe600a8 mainsuspended
Group Check.main:
事實上,Jdb工具現(xiàn)在還存在不少缺陷正待改進,使用時有時會出現(xiàn)一些莫名其妙的錯誤,所以使用時請大家最好聯(lián)網(wǎng),便于查詢。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
多線程/JAVA多線程 - 魔樂培訓(xùn) 高端JAVA培訓(xùn) 魔樂科技JAVA培訓(xùn)
Java筆記(六 程序、進程和線程)
Java 多線程的三種實現(xiàn)方法
多線程編程
Java并發(fā)編程之線程的創(chuàng)建
Java 多線程(四) 多線程訪問成員變量與局部變量
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服