異常
概念:java
指的就是程序在執行過程當中,出現的非正常的狀況,最終會致使JVM的非正常中止
異常體系:程序員
java.lang.throwable : 異常的頂級
子類:安全
1.Exception 表示異常,異常產生後程序員能夠經過代碼的方式糾正,使程序繼續運行, 必需要處理的. 2.Error 嚴重那個錯誤Error,沒法經過處理的錯誤只能事先避免, 經常使用方法: 1. public void printStackTrace():打印異常的詳細信息 包含了異常的類型,異常的緣由,還包括異常出現的位置,在開發和調試階段,都得使用 printStackTrace. 2.public String getMessage(): 獲取發生異常的緣由 提示給用戶的時候,就提示錯誤緣由, 3.public String toString(); 獲取異常的類型和異常描述信息(不用) 分類: 1. 編譯時期異常: checked異常,在編譯時期,就會檢查,若是沒有處理異常,則編譯失敗(如 日期格式化異常) 舉例:ArrayIndexOutOfBoundsException NullPointerException ClassCastException IndexOutOfBoundsException ConcurrenModificationException 2. 運行時期異常: runtime異常,在運行時期,檢查異常,在編譯時期,運行異常不會編譯器檢 測 (不報錯).(如數學異常) 舉例: FileNotFoundException IoException ParseException 異常的產生過程解析
工具類:
[Java] 純文本查看 複製代碼
?
1
2
3
4
5
6
public class ArrayTools{
public static int getElement(int[] arr, int index) {多線程
int element = arr[index]; return element;
}
}
測試類:
[Java] 純文本查看 複製代碼
?
1
2
3
4
5
6
7
public class ExceptionDemo {
public static void main(String[] args){併發
int[] arr = ArrayTools.getElement(arr, 4) System.out.println("num=" + num); System.out.println("over");
}
}
圖解:ide
第二章 異常的處理工具
關鍵字: try, catch, finally, throw, throws throw 用在方法內,用來拋出一個異常對象,將這個異常對象傳遞到調用者處,並結束當前方法執行. 格式: throw new 異常類名(參數); throws 概念: 聲明異常,將問題標識出來,報告給調用者,若是方法內用過throw拋出了編譯時異常,而沒有 捕獲處理,那麼將經過throws進行聲明,讓調用者去處理,,,,,,用在方法聲明之上,用於表示當 前方法不處理異常,而是提醒該方法的調用者來處理異常(拋出異常). 格式: 修飾符 返回值類型 方法名(參數) throws 異常類名1,異常類名2...{ } try....catch 概念: 捕獲異常 try:該代碼塊中編寫可能產生異常的代碼。 try異常 最後只會拋出一個異常 若是沒有捕獲到 交給java虛擬機 catch:用來進行某種異常的捕獲,實現對捕獲到的異常進行處理 在開發中也能夠在catch將編譯器異常轉換成運行期異常處理 若是異常出現的話,會馬上終止程序,若是不想程序終止,因此咱們得處理異常: 1. 該方法不處理,而是聲明拋出,由該方法的調用者來處理(throws)。 2. 在方法中使用try-catch的語句塊來處理異常。 語法格式:
[Java] 純文本查看 複製代碼
?
1
2
3
4
5
6
try{
編寫可能會出現異常的代碼
} catch(異常類型 e) {
處理異常的代碼
//記錄日誌/打印異常信息/繼續拋出異常
}測試
異常使用捕獲處理的三種方式: 1.多個異常分別處理 2.多個異常一次捕獲,屢次處理 (經常使用方式) 3.多個異常一次捕獲一次處理 finally 代碼塊 有一些特定的代碼不管異常是否發生,都須要執行,finally代碼塊中存放的代碼都是必定會被 執行. ......當只有在try或者catch中調用退出JVM的相關方法,此時finally纔不會執行,不然 finally永遠會執行
異常注意事項:this
1.運行時異常被拋出能夠不處理,即不捕獲也不聲明拋出 2.若是父類拋出了多個異常,子類覆蓋父類方法時,只能拋出相同的異常或者是他的子集 3.父類方法沒有拋出異常,子類覆蓋父類該方法時也不可拋出異常,此時子類產生該異常, 只能捕獲處理,不能聲明拋出 4.當多異常處理時,捕獲處理,前邊的類不能是後邊類的父類 5.在try/catch後能夠追加finally代碼塊,其中的代碼必定會被執行,一般用於資源回收 6.若是finally有return語句,永遠返回finally中的結果,避免該狀況
第三章 自定義異常類線程
定義: 1.自定義一個編譯器異常:自定義類 並繼承於java.lang.Exception 2.自定義一個運行時期的異常,:自定義類並繼承於java.lang..RuntimeException. 處理自定義異常類: throws 自定義異常類類名 try catch(自定義異常類類名 變量)
第四章 多線程
併發: (交替執行)指兩個或多個事件在"同一時間段內"發生 並行: (同時執行) 指兩個或多個事件在"同一時刻"發生(同時發生) 進程: 內存中運行的一個應用程序. 每一個進程都有一個獨立的內存空間,一個應用程序能夠同時運行多個進程. 進程也是程序的一次執行過程,是系統運行程序的基本單位 系統運行一個程序便是一個進程從建立,運行到消亡的過程. 線程: 是進程內的一個獨立執行單元(一條代碼執行路徑) 一個程序運行後至少有一個進程,一個進程中能夠包含多個進程 多線程的好處: 效率高 多個線程之間互不影響 線程的調度: 多個線程要併發執行,那個線程被執行,那個線程不被執行,就是調度. 方式: 1.分時調度:全部線程輪流使用CPU,平分佔用CPU的時間 2.搶佔式調度:優先讓優先級高的線程使用CPU;若是優先級相同,則隨機選擇一個 線程執行.
Java使用的是"搶佔式"調度.
主線程:
咱們之前寫的代碼,也在一條線程中執行,該線程叫作"main線程",也成爲"主線程. 若是沒有額外建立線程,那麼程序就只有一個線程,即主線程,此時程序是"單線程" 的單線程的執行特色;
同一個線程內的代碼,從上往下一次執行.
建立多線程程序的第一種方式: 繼承Thread類
實現多線程的第一種方式: 1.定義類,繼承Thread類 2.重寫run()方法,run方法內部是線程要執行的任務 3.建立Thread子類的對象,調用start()方法啓動線程 java.lang.Thread類 : 表示線程,事項了Rannable接口 void start():啓動線程,即讓線程開始執行run()方法中的代碼 注意: 必須調用start() 方法來開啓線程,不能直接調用run() 方法,調用run()會變成 單線程同一線程對象,不能屢次調用start()方法 Java是搶佔式調度,不一樣線程的代碼,執行順序是隨機的
第六天 線程、同步
第一章 線程
一、Java線程調度是搶佔式的,多個線程互相搶奪CPU的執行權。CPU執行哪一個線程是隨機的 二、多線程狀況下,每一個線程都有各自的棧內存。 三、Thread類:表示線程,實現了Runnable接口
經常使用方法:
構造方法
[Java] 純文本查看 複製代碼
?
1
2
3
4
Thread(): 建立Thread對象
Thread(String threadName): 建立Thread對象並指定線程名
Thread(Runnable target): 經過Runnable對象建立Thread對象
Thread(Runnable target, String threadName)
成員方法
[Java] 純文本查看 複製代碼
?
1
2
3
4
void run(): 用於子類重寫,表示線程執行任務,不能直接調用
void start(): 啓動線程,讓線程開始執行run()方法中的代碼
String getName(): 獲取線程的名稱
void setName(String name): 設置線程名稱
靜態方法
[Java] 純文本查看 複製代碼
?
1
2
static Thread currentThread(): 返回對當前正在執行的線程對象的引用
void sleep(long mills): 讓所在線程睡眠指定的毫秒
建立線程方式二:實現Runnable接口
定義Runnable接口實現類,重寫run方法 建立Runnable實現類對象 建立Thread類對象,在構造方法中傳入Runnable實現類對象 經過Thread對象調用start()方法啓動線程
Thread和Runnable的區別
實現Runnable的好處: 一、避免單繼承的侷限性 二、加強了程序的擴展性,下降了程序的耦合性 (線程是Thread,任務是Runnable實現類對象,至關於將線程和任務分離)
匿名內部類方式建立線程
new Thread(new Runnable){ 重寫run() }
線程安全問題
發生場景:多個線程操做共享資源 問題發生緣由: JVM是搶佔式調度,CPU在每一個線程之間切換時隨機的,代碼執行到什麼位置是不肯定的。 在操做共享資源時,一個線程還沒執行完,另外一個線程就來操做,就會出現問題 解決多線程操做共享數據的安全問題 3種方式:同步代碼塊 同步方法 鎖機制 同步代碼塊:使用synchronized關鍵字修飾的代碼塊,並傳入一個看成鎖的對象格式:
[Java] 純文本查看 複製代碼
?
1
2
3
synchronized(鎖對象) {
//操做共享數據的代碼
}
注意:鎖對象能夠是任意類型的一個對象 鎖對象必須是被多個線程共享的惟一對象 鎖對象的做用:只讓一個線程在同步代碼塊中執行 同步的原理: 線程進入同步代碼塊前,會爭奪鎖對象,只有一個線程會搶到 進入同步代碼塊的線程,會持有鎖對象,並執行代碼塊中的代碼 此時同步代碼塊外的線程處於阻塞狀態,只能等待 同步代碼塊內的線程執行完代碼塊,會離開同步代碼塊,並歸還鎖對象給同步代碼塊 此時同步代碼塊外的其餘線程就能夠繼續爭奪鎖對象
同步方法:
非靜態同步方法:(具備默認鎖對象:this)
[Java] 純文本查看 複製代碼
?
1
2
3
public synchronized void method() {
//可能會產生線程安全問題的代碼
}
靜態同步方法
[Java] 純文本查看 複製代碼
?
1
2
3
public static synchronized void method() {
//可能會產生線程安全問題的代碼
}
靜態同步方法的鎖對象:當前類的字節碼對象 獲取一個類的字節碼對象的3種方式: 一、對象.getClass 二、類名.class 三、Class.forName(「類的全路徑」) Lock鎖 成員方法:
[Java] 純文本查看 複製代碼
?
1
2
void lock(): 獲取鎖
void unlock(): 釋放鎖
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
public class RunnableImpl implements Runnable {
Lock lock = new ReentrantLock();
@override
public void run() {
lock.lock(); //加鎖 try{ //操做共享變量的代碼 } finally { lock.unlock(); //在finally中保證釋放鎖 }
}
}
線程安全和效率的特色
程安全,效率低 線程不安全,效率高
線程的狀態
鎖對象,也稱爲「同步鎖」,「對象監視器」
Object類中關於線程的方法:
成員方法:
[Java] 純文本查看 複製代碼
?
1
2
3
4
5
void notify(): 隨機喚醒在同一個鎖對象上的某一個處於等待狀態的線程
void notifyAll(): 喚醒全部在同一個鎖對象上處於等待狀態的線程
void wait(): 讓當前線程處於無限等待狀態
void wait(long timeout): 讓當前線程處於計時等待狀態,時間到或被喚醒後結束此狀態
void wait(ling timeout, int nanos): 讓當前線程處於計時等待狀態,時間到或被喚醒後結束此狀態
線程的生命週期的6種狀態:
一、NEW新建
線程被建立,但沒有調用start()啓動
二、RUNNABLE可運行
調用start()方法後已啓動,但可能正在執行run()方法的代碼,也可能正在等待CPU的調度
三、BLOCKED阻塞
線程試圖獲取鎖,但此時鎖被其餘線程持有
四、WAITING無限等待
經過鎖對象調用無參的wait()進入此狀態 等待其餘線程經過鎖對象執行notify()或notifyAll()才能結束這個狀態
五、TIMED_WAITINGj計時等待
如經過鎖對象調用有參的wait(long millis)或sleep(long millis),則進入此狀態 直到時間結束以前被其餘線程經過鎖對象執行notify()或notifyAll()喚醒,或時間結束自動喚醒
六、TERMINATED終止
run()方法結束(執行結束,或內部出現異常),則進入此狀態
Object類成員方法:[Java] 純文本查看 複製代碼?12void notifyAll(): 喚醒全部在同一個鎖對象上處於等待狀態的線程void wait(long timeout): 讓當前線程處於計時等待狀態,時間到或被喚醒後結束此狀態