異常是程式在執行期發生的不正常的事件,它會打斷指令的正常執行流程。
設計良好的程式應該在異常發生時提供處理這些不正常事件的方法,使程式不會因爲異常的發生而阻斷或產生不可預見的結果。
Java語言使用例外處理機制 機製爲程式提供了例外處理的能力
Java程式執行過程中所發生的異常事件從嚴重性可分爲兩類:
錯誤(Error):JVM系統內部錯誤或資源耗盡等嚴重情況,屬於JVM需要負擔的責任,這一類異常事件無法恢復或不可能捕獲,將導致應用程式中斷。
異常(Exception):其它因程式設計錯誤或偶然的外在因素導致的一般性問題。這類異常得到恰當的處理時,程式有機會恢復至正常執行狀況。
RuntimeException:又叫做非受檢性異常,編譯器不要求強制處置的異常。一般是指程式設計時的邏輯錯誤。是程式設計師應該積極避免其出現的異常
RuntimeException/執行時異常/非受檢性異常 描述 ClassCastException 型別轉換異常 ArrayIndexOutOfBoundsException 陣列下標越界異常 NullPointerException 空指針異常 ArithmeticException 算數類異常 一般性異常:又叫做受檢性異常,編譯器要求必須處置的異常。指的是程式在執行時由於外界因素造成的一般性異常。
一般性異常/受檢性異常 ClassNotFoundException 類的位元組碼檔案未找到異常 FileNotFoundException 檔案未找到異常 IOException 操作檔案時異常 SQLException 數據庫異常
- Java程式在執行過程中如果出現異常,會自動生成一個異常類物件,該異常物件將被自動提交給JVM,這個過程稱爲拋出(throw)異常。
- 當JVM接收到異常物件時,會尋找能處理這一異常的程式碼並把當前異常物件交給其處理,這一過程稱爲捕獲(catch)異常和處理異常。
- 如果JVM找到可以以捕獲異常的程式碼,將異常物件交給其處理
- 如果JVM找不到可以捕獲異常的程式碼,則執行時系統將終止,相應的Java程式也將退出。
語法:
try{
//…存放可能發生異常的程式碼…
}catch(例外處理的類 e){//捕獲異常
//…處理異常…
}finally{
//不管是否發生異常,finally裡的程式碼塊都會被執行
}
注意:finally程式碼塊可以寫可以不寫
含義:拋出異常
作用在宣告方法時,拋出該異常物件,讓呼叫方處理
含義:拋出異常
作用:可以建立一個異常物件將其拋出
進程是系統進行資源分配和呼叫的獨立單元,每一個進程都有它的獨立的記憶體空間和系統資源。
單進程操作系統:一次只能執行一個任務
多進程操作系統:一次可以執行多個任務
理論上是可以的
什麼是執行緒?
執行緒是進程裡的一條執行路徑,每個執行緒同享進程裏面的記憶體空間和系統資源
執行緒和進程的關係?
進程:進程之間的記憶體空間和系統資源是獨立的
執行緒:同一個進程裡的執行緒之間是共用記憶體空間和系統資源的
進程裡:可以有一條或一條以上的執行緒
進程裡只有一條執行緒的情況下,這條執行緒就叫做主執行緒
進程裡有多條執行緒的情況下,只有一條執行緒叫做主執行緒
Ps:執行緒是在進程裡的,他們是包裹關係
99%都是多執行緒應用
執行緒類:建立MyThread類,繼承Thread,重寫run方法
使用: //建立子執行緒 MyThread t = new MyThread(); //啓動子執行緒 t.start();
任務類:建立Task類,實現Runnable介面裏的run方法
使用: //建立子執行緒,並放入任務 Thread t = new Thread(new Task()); //啓動子執行緒 t.start();
帶返回值的任務類
需求:編寫一個多執行緒的應用程式,主執行緒列印1-100之間的數位,子執行緒列印200-300之間的數位,觀察其輸出的結果,體會多執行緒互相爭搶資源的場景
使用執行緒類的步驟:
- 建立MyThread類,繼承Thread,重寫run方法
- 建立MyThread類的物件
- 利用物件呼叫start方法
經典面試題:請問當我們編寫一個單純的main方法時,此時該程式是否爲單執行緒的?爲什麼?
不是,是多執行緒程式,當我們執行專案時,Java垃圾回收器也在後台默默執行,垃圾回收器就是一個後臺執行緒
需求:在主執行緒中建立三個的子執行緒,並且設定不同優先順序,觀察其優先順序對執行緒執行結果的」影響」。
優先級別由低到高:1~10
a.setPriority(Thread.MAX_PRIORITY); //10 b.setPriority(Thread.NORM_PRIORITY);//5 c.setPriority(Thread.MIN_PRIORITY);//1
利用父類別的構造方法傳入執行緒的名字
通過Thread.currentThread().getName()獲取到當前執行緒的名字
需求:編寫一個抽取學員回答問題的程式,要求倒數三秒後輸出被抽中的學員姓名
public class Test01 { public static void main(String[] args) throws InterruptedException { String[] names = {"小明","小紅","小亮","小飛","小雲"}; Random ran = new Random(); int randomIndex = ran.nextInt(names.length); for (int i = 3; i > 0; i--) { System.out.println(i); Thread.sleep(1000);//休眠1000毫秒 } System.out.println(names[randomIndex]); } }
注意:
- Thread類的靜態方法
- 寫在哪個執行緒裡就休眠當前執行緒
含義:強制讓當前執行緒退出CPU資源
需求:建立兩個執行緒A,B,分別各列印100次,從1開始每次增加1,其中B一個執行緒,每列印一次,就禮讓一次,觀察實驗結果
public class Test01 { public static void main(String[] args) { new A().start(); new B().start(); } } class A extends Thread{ @Override public void run() { for (int i = 1; i <= 100; i++) { System.out.println("A:" + i); } } } class B extends Thread{ @Override public void run() { for (int i = 1; i <= 100; i++) { System.out.println("B:" + i); Thread.yield();//禮讓 } } }
注意:
- Thread類的靜態方法
- 寫在哪個執行緒裡就讓當前執行緒退出CPU資源
正確理解禮讓:禮讓後,當前執行緒一定會退出CPU資源,退出後當前執行緒立刻恢復到搶資源的狀態
需求:主執行緒和子執行緒各列印200次,從1開始每次增加1,當主執行緒列印到10之後,讓子執行緒先列印完再列印主執行緒
t.join(); --> 讓t執行緒加入到當前執行緒,當前執行緒就阻塞
public class Test01 { public static void main(String[] args) throws InterruptedException { MyThread t = new MyThread(); t.start(); for (int i = 1; i <= 200; i++) { System.out.println("主執行緒:" + i); if(i == 10){ t.join();//讓t執行緒加入到當前執行緒,當前執行緒就阻塞 } } } } class MyThread extends Thread{ @Override public void run() { for (int i = 1; i <= 200; i++) { System.out.println("子執行緒:" + i); } } }
Thread.currentThread().isInterrupted() 獲取當前執行緒是否死亡
true - 死亡 false-沒有死亡
執行緒物件.interrupt(); 改變執行緒狀態
含義:守護執行緒又叫做後臺執行緒,守護執行緒默默守護着前臺執行緒,當前台執行緒全部去消亡後,守護執行緒也會自動消亡
執行緒物件.setDaemon(true);//設定當前執行緒爲守護執行緒
垃圾回收器就是一個守護執行緒
a) 新建狀態
i. 在程式中用構造方法建立了一個執行緒物件後,新的執行緒物件便處於新建狀態,此時,它已經有了相應的記憶體空間和其它資源,但還處於不可執行狀態。新建一個執行緒物件可採用執行緒構造方法來實現。
ii. 例如:Thread thread=new Thread();
b) 就緒狀態
i. 新建執行緒物件後,呼叫該執行緒的start()方法就可以啓動執行緒。當執行緒啓動時,執行緒進入就緒狀態。此時,執行緒將進入執行緒佇列排隊,等待CPU呼叫,這表明它已經具備了執行條件。
c) 執行狀態
i. 當就緒狀態的執行緒被呼叫並獲得處理器資源時,執行緒就進入了執行狀態。此時,自動呼叫該執行緒物件的run()方法。run()方法定義了該執行緒的操作和功能。
d) 阻塞狀態
i. 一個正在執行的執行緒在某些特殊情況下,如被人爲掛起,將讓出CPU並暫時中止自己的執行,進入阻塞狀態。在可執行狀態下,如果呼叫sleep(2000)、wait()等方法,執行緒都將進入阻塞狀態。阻塞時,執行緒不能進入排隊佇列,只有當引起阻塞的原因被消除後,執行緒纔可以轉入就緒狀態。
e) 死亡狀態
執行緒呼叫stop()方法時或run()方法執行結束後,執行緒即處於死亡狀態。處於死亡狀態的執行緒不具有繼續執行的能力。