異常、線程

異常
概念: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): 讓當前線程處於計時等待狀態,時間到或被喚醒後結束此狀態

相關文章
相關標籤/搜索