1. 程式人生 > 實用技巧 >小白—職場之Java基礎篇

小白—職場之Java基礎篇

java基礎篇

java基礎 目錄
1、java是一種什麼語言,jdk,jre,jvm三者的區別
2、java 1.5之後的三大版本
3、java跨平臺及其原理
4、java 語言的特點
5、什麼是位元組碼,位元組碼的好處
6、java 和 c++ 的區別
7、java的三大特性
8、java中的基本資料型別和引用資料型別及其區別
9、switch(expr),expr支援哪些資料型別
10、int 和 Integer 有什麼區別,怎麼理解自動拆箱,自動裝箱
11、計算2^3效率最高的方法是
12、Math.round(temp)
13、float f=3.4;是否正確
14、short s1 = 1; s1 = s1 + 1;有錯嗎?short s1 = 1; s1 += 1;有錯嗎
15、java中的註釋
16、java中的訪問修飾符
17、重寫與過載的區別
18、運運算元 &和&&的區別
19、Java 有沒有 goto
20、this關鍵字的用法
21、super關鍵字的用法
22、java 的final 關鍵字
23、break ,continue ,return 的區別及作用
24、在 Java 中,如何跳出當前的多重巢狀迴圈
25、hashCode 與 equals
26、抽象類和介面的區別是什麼
27、什麼是介面****
28、靜態變數與非靜態變數的區別
29、值傳遞和引用傳遞的區別是什麼****
30、什麼是反射
31、String 類中常用的方法
32、String 中的==和 equals 的區別
33、Java 中的 String,StringBuilder,StringBuffer 三者的區別
34、Java中final、finally和finalize的區別
35、Java裡可不可以有多繼承
36、HashMap 和 Hashtable 的區別
37、Map 集合有哪些實現類,分別具有什麼特徵****
38、解決 hashmap 執行緒不安全問題
39、Hashmap 的底層實現原理
40、hash 碰撞怎麼產生,怎麼解決****
41、HashMap 為什麼需要擴容
42、 如何遍歷 Map 集合
43、 ArrayList 與 LinkedList 區別****
44、ArrayList 與 LinkedList 區別
45、如何使用的 List 集合來保證執行緒安全
46、IO 和 NIO 的區別
47、在 Java 中要想實現多執行緒程式碼有三種手段
48、Thread 類中的 start() 和 run() 方法有什麼區別
49、Java 中 notify 和 notifyAll 有什麼區別
50、Java 多執行緒中呼叫 wait() 和 sleep()方法有什麼不同
51、什麼是執行緒安全
52、Java中的 volatile 變數是什麼
53、執行緒的狀態
54、實現執行緒同步有三種方式
55、Java中的鎖有幾種方式
56、Lock的幾個實現類
57、執行緒間通訊的幾種實現方式
58、synchronized 和 Lock 的區別和應用場景
59、為什麼要用執行緒池
60、如何建立執行緒池
61、java中的異常體系
62、throw 和 throws 的區別
63、說出 5 個常見的異常

1、java是一種什麼語言,jdk,jre,jvm三者的區別?

     java是一種完全面向物件的程式語言,具有簡單性、面向物件、分散式、健壯性、安全性、平臺獨立與可移植性、多執行緒、動態性等特點,它吸收了c++的優點,去掉了c++中多繼承,指標等讓人難於理解的概念。java語言採用Unicode編碼標準。

     JDK(Java Development Kit)是針對 Java 開發員的產品,是整個 Java 的核心,包括了 Java 執行環境 JRE、Java 工具和 Java 基礎類庫。

     Java Runtime Environment(JRE)是執行 JAVA 程式所必須的環境的集合,包含 JVM 標準實現及 Java 核心類庫。

    JVM 是 Java Virtual Machine(Java 虛擬機器器)的縮寫,是整個 java 實現跨平臺的最核心的部分,能夠執行以 Java 語言寫作的軟體程式。



2、java 1.5之後的三大版本?

java SE java標準版

java EE java企業版

java ME java微型版

3、java跨平臺及其原理?

所謂的跨平臺就是java原始碼經過一次編譯以後,可以在不同的作業系統上執行

原理:經過編譯的 .class 檔案執行在java虛擬機器器上,並非直接執行在作業系統上,只要安裝滿足不同作業系統的jvm即可。

4、java 語言的特點?

1、面向物件。java 是面嚮物件語言,即滿足面向物件的基本特徵(封裝,繼承,多型)。封裝是將 屬性,方法等放在一個類中,體現了java語言的安全性,繼承是子類繼承了父類後便有了父類的特性,多型則是父類的引用指向子類的地址,執行不同的操作,繼承和多型體現了java語言的靈活性,易擴充套件性。

2、跨平臺。jvm實現java語言的跨平臺。

3、支援網路程式設計。

4、支援多執行緒。

5、健壯性。java語言的強型別機制,異常處理機制,GC垃圾自動收集機制。

5、什麼是位元組碼,位元組碼的好處?

位元組碼:java 經過 javac 命令產生的 .class 檔案就是位元組碼。

位元組碼的好處:1、在一定程度上解決瞭解釋性語言效率低下的問題。2、不針對特定的機器,保留了解釋性語言的可移植性。

6、java 和 c++ 的區別?

java和c++都是面嚮物件語言。因此都有面向物件的基本特性封裝,繼承,多型。它們的區別如下:

1、java不提供指標來直接訪問記憶體,程式記憶體更加安全。

2、java中是單繼承,c++中支援多繼承。

3、java中有記憶體管理機制,無需程式設計師手動釋放記憶體。

7、java的三大特性?

封裝: 把方法、變數封裝在類中,提高程式碼的安全性

繼承: java中為單繼承,提高程式碼的重用性

多型: 多型就是同一個類或者介面,使用不同的例項因而執行不同的操作,提高程式碼的靈活性

8、java中的基本資料型別和引用資料型別及其區別?

  • 8種基本資料型別
說明 所佔記憶體大小(位元組) 取值範圍 預設值
byte java中最小的資料型別 1 \({-2^7}\)~\({2^7}\)-1 0
short 短整型 2 \({-2^{15}}\)~\({2^{15}}\)-1 0
int 整型 4 \({-2^{31}}\)~\({2^{31}}\)-1 0
long 長整型 8 \({-2^{63}}\)~\({2^{63}}\)-1 0L
float 單精度 4 -3.40E+38 ~ +3.40E+38 0
double 雙精度 2 -1.79E+308 ~ +1.79E+308 0
char 字元型 2 0~65535 null
boolean 布林型 1 true,false false
  • 引用資料型別

類,介面型別,陣列型別,列舉型別,註解型別

  • 基本資料型別與引用資料型別的區別

     基本資料型別在被建立時,會在棧上分配空間,直接將之儲存在棧中。而引用資料型別在被建立時,首先會在棧上分配空間,將其引用存在棧空間中,然後在堆中開闢記憶體,值存放在堆記憶體中,棧中的引用指向堆中的地址。

9、switch(expr),expr支援哪些資料型別?

在java5以前,expr支援 byte,short,int,char 四種資料型別,在java5以後,又多了列舉enum型別,java7又增加了string型別,到目前並比支援long型別。

10、int 和 Integer 有什麼區別,怎麼理解自動拆箱,自動裝箱?

int 是基本資料型別,預設值是0

integer是引用型別,是int 的包裝類,預設值是 null

自動拆箱:將包裝型別自動轉化為對應的基本資料型別。

自動裝箱:將基本型別自動轉化為對應的引用型別。

11、計算2^3效率最高的方法是?

計算2^3效率最高的方法是:2<<(3-1)

12、Math.round(temp) ?

四捨五入的原理是在原來的引數上加0.5,然後進行向下取整。

13、float f=3.4;是否正確?

不正確。3.4是雙精度型別,賦值給float需要強制型別轉換,float f=(float)3.4,可以寫成 float f=3.4F。

14、short s1 = 1; s1 = s1 + 1;有錯嗎?short s1 = 1; s1 += 1;有錯嗎?

short s1 = 1; s1 = s1 + 1 不正確。因為 1是int型別,因此 s1+1 也是int型別,在執行 s1=s1+1 時,需要將int型別的s1+1賦值給short型別的s1,大轉小可能會有精度損失,無法顯示轉化。

short s1 = 1; s1 += 1 正確。因為 s1+=1 相當於s1=(short)(s1+1),存在隱含的強制型別轉換。

15、java中的註釋?

定義:註釋是用來解釋說明程式的文字。分為:

單行註釋:// 註釋的文字

多行註釋:/* 註釋的文字 /

檔案註釋:/
* 註釋的文字 **/

16、java中的訪問修飾符?

java中的訪問修飾符有:public,private,protected,以及不寫(預設)。



17、重寫與過載的區別?

重寫: 至少發生在兩個類中,並且類與類具有繼承或者實現關係,表示子類中的方法具有與父類方法中完全相同的方法名稱,返回值,引數。子類中的方法覆蓋父類的方法,體現了多型性。

過載: 發生在同一個類中,多個方法名稱相同,引數型別,個數和順序不同的方法發生過載現象,與返回值無關。

18、運運算元 &和&&的區別?

&:無論左邊true還是false,右邊也會進行判斷。

&&:如果左邊為false,有邊就不會進行判斷,因此&&比&效率高。

注意:邏輯或運運算元(|)和短路或運運算元(||)的差別也是如此。

19、Java 有沒有 goto?

goto 是 Java 中的保留字,在目前版本的 Java 中沒有使用。

20、this關鍵字的用法?

1.普通的直接引用,this相當於是指向當前物件本身。

2.形參與成員名字重名,用this來區分:

public Person(String name, int age) {
this.name = name;
this.age = age;
}

3.呼叫本類的建構函式:

class Person{
private String name;
private int age; public Person() {
} public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this(name);
this.age = age;
}
}

21、super關鍵字的用法?

1.普通的直接引用。

2.呼叫父類中與子類重名的方法。

2.呼叫父類的建構函式。

22、java 的final 關鍵字?

在java中,final關鍵字可以修飾類,變數和方法。被final修飾後以下特點:

final修飾類:final修飾的類不能被繼承。

final修飾變數:final修飾的變數是常量,不能改變。

final修飾方法:final修飾的方法不能被重寫。

23、break ,continue ,return 的區別及作用?

break:跳出當前迴圈

continue:結束本次迴圈,進行下次迴圈

return:返回

24、在 Java 中,如何跳出當前的多重巢狀迴圈?

在外面的迴圈語句前定義一個標號

ok:
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
system.out.println("i="+i+",j="+j);
if(j==5)break ok;
}
}

25、hashCode 與 equals?

如果兩個物件equals()方法相等則它們的hashCode返回值一定要相同,如果兩個物件的hashCode返回值相同,但它們的equals()方法不一定相等。

兩個物件的hashCode()返回值相等不能判斷這兩個物件是相等的,但兩個物件的hashcode()返回值不相等則可以判定兩個物件一定不相等。

26、抽象類和介面的區別是什麼?

介面中的方法都是抽象的,抽象類中可以有抽象方法,也可以有非抽象方法。

在jdk1.8以後介面中也可以有用defaule關鍵字修飾的普通方法

27、什麼是介面?

介面是一種規範,java中的介面:interface

28、靜態變數與非靜態變數的區別

靜態變數 非靜態變數
呼叫方式 靜態變數只能通過 “ 類名.變數名 ” 呼叫 非靜態變數通過例項化物件名呼叫
共享方式 靜態變數是全域性變數,被類的所有例項化物件共享 非靜態變數是區域性變數,不共享
相互訪問方式 靜態變數無法訪問非靜態變數 非靜態變數可以訪問靜態變數

29、值傳遞和引用傳遞的區別是什麼?

值傳遞: 在方法的呼叫過程中,實參把它的實際值傳遞給形參,此傳遞過程就是將實參的值複製一份傳遞到函式中。

引用傳遞: 引用傳遞彌補了值傳遞的不足,如果傳遞的資料量很大,直接復過去的話,會佔用大量的記憶體空間,而引用傳遞就是將物件的地址值傳遞過去,函式接收的是原始值的首地址值。在方法的執行過程中,形參和實參的內容相同,指向同一塊記憶體地址,也就是說操作的其實都是源資料,所以方法的執行將會影響到實際物件。

30、什麼是反射?

JAVA 反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性。

31、String 類中常用的方法?

方法 說明
split() 把字串分割成字串陣列
indexOf() 從指定字元提取索引位置
append() 追加字元或字串
trim() 去掉字串兩端的空格
replace() 替換
hashCode() 返回字串的雜湊值
subString() 擷取字串
equals() 比較字串是否相等
length() 獲取字串長度
concat() 將指定字串連線到此字串的結尾

32、String 中的==和 equals 的區別?

"=="比較的是兩個字串的記憶體地址。 "equals"比較的是兩個字串的實際值

33、Java 中的 String,StringBuilder,StringBuffer 三者的區別?

String: 字串常量,底層用 final 關鍵字修飾,底層實際在維護 char 型別的字元陣列,當每次對String進行改變時,都需要生成一個新的String物件,然後將指標指向一個新的物件。

//底層用 final 關鍵字修飾,底層實際在維護 char 型別的字元陣列
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}

StringBuilder: 字串變數,執行緒安全,用於多執行緒操作

StringBuffer : 字串變數,非執行緒安全,用於單執行緒操作

34、Java中final、finally和finalize的區別?

final: 修飾符,java 中的關鍵字。可用於修飾類,變數,方法,有最終的意思。

修飾的物件 說明
final 修飾類 表明該類不能被其他類所繼承,但要注意:final類中所有的成員方法都會隱式的定義為final方法。
final 修飾變數 final成員變量表示常量,只能被賦值一次,賦值後其值不再改變
final 修飾方法 final 修飾的方法不能被重寫

finally: finally 是在異常裡經常用到的, 就是 try 和 cach 裡的程式碼執行完以後,必須要執行的方法,我們經常在 finally 裡寫一些關閉資源的方法,比如說關閉資料庫連線,或者關閉 IO 流.

finalize: finalize是方法名,java技術允許使用finalize()方法在垃圾收集器將物件從記憶體中清除出去之前做必要的清理工作

35、Java裡可不可以有多繼承?

java中不允許多繼承,比如類A不能同時繼承類B和類C,若要有次類需求,考慮用介面。

36、HashMap 和 Hashtable 的區別?

HashMap 和 Hashtable是Map介面的實現類,它們大體有一下幾個區別:

  1. 繼承的父類不同。HashMap是繼承自AbstractMap類,而HashTable是繼承自Dictionary類。
  2. 執行緒安全性不同。Hashtable 中的方法是Synchronize的,而HashMap中的方法在預設情況下是非Synchronize的。Hashtable 是現成安全的,HashMap是非執行緒安全的。
  3. key和value是否允許null值。Hashtable中,key和value都不允許出現null值。但是如果在Hashtable中有類似put(null,null)的操作,編譯同樣可以通過,因為key和value都是Object型別,但執行時會丟擲NullPointerException異常,這是JDK的規範規定的。HashMap中,null可以作為鍵,這樣的鍵只有一個;可以有一個或多個鍵所對應的值為null。當get()方法返回null值時,可能是 HashMap中沒有該鍵,也可能使該鍵所對應的值為null。因此,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵, 而應該用containsKey()方法來判斷。

37、Map 集合有哪些實現類,分別具有什麼特徵?

實現類 特徵
HashMap 執行緒不安全的鍵值對集合,允許 null 值,key 和 value 都可以
HashTable 執行緒安全的鍵值對集合,不允許 null 值,key 和 value 都不可以
TreeMap 能夠把它儲存的記錄根據鍵排序,預設是按升序排序

38、解決 hashmap 執行緒不安全問題?

  1. Collections.synchronizedMap() 方法
  2. java.util.concurrent.ConcurrentHashMap 類

39、Hashmap 的底層實現原理?

     在JDK1.6,JDK1.7中,HashMap採用位桶+連結串列實現,即使用連結串列處理衝突,同一hash值的鍵值對會被放在同一個位桶裡,當桶中元素較多時,通過key值查詢的效率較低。

     而JDK1.8中,HashMap採用位桶+連結串列+紅黑樹實現,當連結串列長度超過閾值(8),時,將連結串列轉換為紅黑樹,這樣大大減少了查詢時間。

     當我們建立 hashmap 時 會先建立一個陣列,當我們用 put 方法存資料時,先根據 key 的 hashcode 值計算出 hash 值,然後用這個雜湊值確定在陣列中的位置,再把 value 值放進去,如果這個位置本來沒放 東西,就會直接放進去,如果之前就有,就會生成一個連結串列,把新放入的值放在頭部,當用 get 方法取值時,會先根據 key 的 hashcode 值計算出 hash 值,確定位置,再根據 equals 方法從該位置上的連結串列中取出該 value 值。

40、hash 碰撞怎麼產生,怎麼解決?

    物件Hash的前提是實現equals()和hashCode()兩個方法,那麼HashCode()的作用就是保證物件返回唯一hash值,但當兩個物件計算值一樣時,這就發生了碰撞衝突。如下將介紹如何處理衝突,當然其前提是一致性hash。

     解決hash碰撞有以下幾種方法:

  • 開放地址法

     開放地執法有一個公式:Hi=(H(key)+di) MOD m i=1,2,…,k(k<=m-1) 其中,m為雜湊表的表長。di 是產生衝突的時候的增量序列。如果di值可能為1,2,3,…m-1,稱線性探測再雜湊。如果di取1,則每次衝突之後,向後移動1個位置.如果di取值可能為1,-1,2,-2,4,-4,9,-9,16,-16,…kk,-kk(k<=m/2),稱二次探測再雜湊。如果di取值可能為偽隨機數列。稱偽隨機探測再雜湊。

  • 再雜湊法

     當發生衝突時,使用第二個、第三個、雜湊函式計算地址,直到無衝突時。缺點:計算時間增加。比如上面第一次按照姓首字母進行雜湊,如果產生衝突可以按照姓字母首字母第二位進行雜湊,再衝突,第三位,直到不衝突為止。

  • 鏈地址法(拉鍊法)

將所有關鍵字為同義詞的記錄儲存在同一線性連結串列中。如下:



41、HashMap 為什麼需要擴容?

     當 hashmap 中的元素個數超過陣列大小loadFactor 時,就會進行陣列擴容,loadFactor 的預設值為 0.75,也就是說,預設情況下,陣列大小為 16,那麼當hashmap 中元素個數超過 160.75=12 的時候,就把陣列的大小擴充套件為216=32,即擴大一倍。然後重新計算每個元素在陣列中的位置,而這是一個非常消耗效能的操作,所以如果我們已經預知 hashmap 中元素的個數,那麼預設元素的個數能夠有效的提高 hashmap 的效能。比如說,我們有 1000 個元素new HashMap(1000), 但是理論上來講 new HashMap(1024)更合適,不過上面annegu 已經說過,即使是 1000,hashmap 也自動會將其設定為 1024。 但是newHashMap(1024)還不是更合適的,因為 0.751000<1000, 也就是說為了讓 0.75*size>1000, 我們必須這樣 newHashMap(2048)才最合適,避免了resize 的問題。

42、 如何遍歷 Map 集合?

     先獲取 Map 中的 key 的 set 集合 map.keySet(); 通過遍歷 key 集合,獲取 value 值。Map.get(key)先獲取 Entry 集合 map.entrySet(); 遍歷 entrySet 分別獲取 key value。

43、 ArrayList 與 LinkedList 區別?

     ArrayList 使用陣列方式儲存資料,所以根據索引查詢資料速度快,而新增或者 刪除元素時需要設計到位移操作,所以比較慢。

     LinkedList 使用雙向連結方式儲存資料,每個元素都記錄前後元素的指標, 所以插入、刪除資料時只是更改前後元素的指標指向即可,速度非常快,然後通過下標查詢元素時需要從頭開始索引,所以比較慢,但是如果查詢前幾個元素或 後幾個元素速度比較快。

     ArrayList 與 LinkedList 都是執行緒不安全的。

44、 Java中的ArrayList的初始容量和容量分配?

ArrayList是經常會被用到的,一般情況下,使用的時候會像這樣進行宣告:

List arrayList = new ArrayList();

如果像上面這樣使用預設的構造方法,初始容量被設定為10。當ArrayList中的元素超過10個以後,會重新分配記憶體空間,使陣列的大小增長到16。

可以通過除錯看到動態增長的數量變化:10->16->25->38->58->88->...

也可以使用下面的方式進行宣告:

List arrayList = new ArrayList(4);

將ArrayList的預設容量設定為4。當ArrayList中的元素超過4個以後,會重新分配記憶體空間,使陣列的大小增長到7。

可以通過除錯看到動態增長的數量變化:4->7->11->17->26->...

那麼容量變化的規則是什麼呢?請看下面的公式:

((舊容量 * 3) / 2) + 1

45、 如何使用的 List 集合來保證執行緒安全?

1、使用 Vector

2、使用 Collections 中的方法 synchronizedList 將 ArrayList 轉換為執行緒安全的 List

3、使用 java.util.current 包下的 CopyOnWriteArrayList(推薦)

46、IO 和 NIO 的區別?

這個NIO是JDK1.7以後有的 ,它們倆的主要區別是 :io 是面向流是阻 塞 io,nio 是面向緩 衝,非阻塞的 io; io 話每次從流中讀取一 個多個位元組 ,直到讀取完所有的位元組 ,沒有快取到 任何地方 .nio 讀取的是資料是有快取 ,就是說他讀取的資料是 在緩衝裡讀的 . 另外的話 ,java 中的各種 io 是阻塞的 .就是說一個執行緒呼叫 read 或 者 write()時 ,這個執行緒就已經被阻塞了,直到讀取到一 些資料為止 ,或者是完全寫入。在這個過程中不能幹其他的事情 . nio 的非阻塞模式 ,當傳送一個讀取資料的請求的時候 ,如果沒有讀取到可用的資料 ,就什麼也不會 獲取 ,且不會讓執行緒阻塞寫也是這樣。非阻塞的IO的空閒時間可用用來做其他的操作所以,一個單 獨的非阻塞線 程可以管理 多個輸入和輸出通道,另外 NIO 還有一 個 selector(選 擇 器 ),它是可以管理多個輸入輸出的通道.

47、在 Java 中要想實現多執行緒程式碼有三種手段?

一種是繼承 Thread 類

另一種就是實現 Runnable 介面

最後一種就是實現 Callable 介面

(第四種也是實現 callable 介面,只不過有返回值而已)

48、Thread 類中的 start() 和 run() 方法有什麼區別?

     start()方法被用來啟動新建立的執行緒,而且 start()內部呼叫了 run()方法,這和直接呼叫 run()方法的效果不一樣。當你呼叫 run()方法的時候,只會是在原來的執行緒中呼叫,沒有新的執行緒啟動,start()方法才會啟動新執行緒。

49、Java 中 notify 和 notifyAll 有什麼區別?

     notify()方法不能喚醒某個具體的執行緒,所以只有一個執行緒在等待的時候它

才有用武之地。而 notifyAll()喚醒所有執行緒並允許他們爭奪鎖確保了至少有一

個執行緒能繼續執行。

50、Java 多執行緒中呼叫 wait() 和 sleep()方法有什麼不同?

     Java 程式中 wait 和 sleep 都會造成某種形式的暫停,它們可以滿足不同的需要。wait()方法用於執行緒間通訊,如果等待條件為真且其它執行緒被喚醒時它會釋放鎖,而 sleep()方法僅僅釋放 CPU 資源或者讓當前執行緒停止執行一段時間,但不會釋放鎖。

51、什麼是執行緒安全

     多個執行緒同時執行一段程式碼。如果每次執行結果和單執行緒執行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是執行緒安全的。同一個例項物件在被多個執行緒使用的情況下也不會出現計算失誤,也是執行緒安全的,反之則是執行緒不安全的。

52、Java中的 volatile 變數是什麼?

     Volatile: 一個共享變數(類的成員變數、類的靜態成員量)被volatile修飾之後,那麼就具備了兩層語義:

               a.保證了不同執行緒對這個變數進行操作時的可見性,即一個執行緒修改了某個變數的值,這新值對其他執行緒來說是立即可見的。

               b.禁止進行指令重排序。但是它並不能保證操作的原子性。

     應用場景:在只涉及可見性,針對變數的操作只是簡單的讀寫(保證操作的

原子性)的情況下可以使用volatile來解決高併發問題,如果這時針對變數的操作是非原子的操作,這時如果只是簡單的i++式的操作,可以使用原子類atomic類來保證操作的原子性(採用CAS實現),如果是複雜的業務操作,那麼捨棄volatile,採用鎖來解決併發問題(synchronized或者Lock)。

53、執行緒的狀態?

實執行緒一般具有五種狀態,即建立、就緒、執行、阻塞、終止。

  1. 新建( new ):新建立了一個執行緒物件。
  2. 可執行( runnable ):執行緒物件建立後,其他執行緒(比如 main 執行緒)呼叫了該物件的start ()方法。該狀態的執行緒位於可執行執行緒池中,等待被執行緒排程選中,獲 取 cpu 的使用權 。
  3. 執行( running ):可執行狀態( runnable )的執行緒獲得了 cpu 時間片( timeslice ),執行程式程式碼。
  4. 阻塞( block ):阻塞狀態是指執行緒因為某種原因放棄了 cpu 使用權,也即讓出了 cpu timeslice ,暫時停止執行。直到執行緒進入可執行( runnable )狀態,才有機會再次獲得 cpu timeslice 轉到執行( running )狀態。阻塞的情況分三種:

             (一). 等待阻塞:執行( running )的執行緒執行 o.wait ()方法,JVM 會把該執行緒放 入等待佇列( waitting queue )中。

             (二). 同步阻塞:執行( running )的執行緒在獲取物件的同步鎖時, 若該同步鎖被別的執行緒佔用,則 JVM 會把該執行緒放入鎖池( lock pool )中。

              (三). 其他阻塞: 執行( running )的執行緒執行 Thread . sleep ( long ms )或 t.join ()方法,或者發出了 I / O 請求時,JVM 會把該執行緒置為阻塞狀態。當 sleep ()狀態超時、 join ()等待執行緒終止或者超時、或者 I / O 處理完畢時,執行緒重新轉入可執行( runnable )狀態。
  5. 死亡( dead ):執行緒 run ()、 main () 方法執行結束,或者因異常退出了 run ()方法,則該執行緒結束生命週期。死亡的執行緒不可再次復生。

54、實現執行緒同步有三種方式?

1、同步程式碼塊:在程式碼塊上加上“synchronized”關鍵字的話,則此程式碼塊就稱為同步代 碼塊。

同步程式碼塊格式:
synchronized(監視物件){
需要同步的程式碼 ;
}

解釋:監視物件有三種:物件、String、.class 檔案(只要是不變的物件都可以做監 視物件)

2、同步方法

同步方法定義格式:
synchronized 方法返回值 方法名稱(引數列表){
}
在方法上加 synchronized,是把當前物件做為監視器

3、同步鎖

 Lock lock = new ReentrantLock();(可以在類中直接 new)
lock.lock(); 中間的程式碼塊進行加鎖 lock.unlock();

55、Java中的鎖有幾種方式?

  1. Synchronized
  2. Lock

Synchronized的侷限性:

1).如果這個獲取鎖的執行緒由於要等待IO或者其他原因(比如呼叫sleep方法)被阻塞了,但是又沒有釋放鎖,其他執行緒便只能乾巴巴地等待。(不能主動釋放鎖)

2).當有多個執行緒讀寫檔案時,讀操作和寫操作會發生衝突現象,寫操作和寫操作會發生衝突現象,但是讀操作和讀操作不會發生衝突現象如果多個執行緒都只是進行讀操作,所以當一個執行緒在進行讀操作時,其他執行緒只能等待無法進行讀操作。(不分情況,一律鎖死)

56、Lock的幾個實現類?

ReentrantLock是一個可重入的互斥鎖,又被稱為“獨佔鎖”

ReadWriteLock,顧名思義,是讀寫鎖。它維護了一對相關的鎖 ——“讀取鎖”和“寫入鎖”,一個用於讀取操作,另一個用於寫入操作。他的兩個實現類讀鎖readerLock和寫鎖writerLock。

57、執行緒間通訊的幾種實現方式?

1、使用 volatile 關鍵字。基於 volatile 關鍵字來實現執行緒間相互通訊是使用共享記憶體的思想,大致意思就是多個執行緒同時監聽一個變數,當這個變數發生變化的時候 ,執行緒能夠感知並執行相應的業務。這也是最簡單的一種實現方式

2、使用Object類的wait() 和 notify() 方法。Object類提供了執行緒間通訊的方法:wait()、notify()、notifyaAl(),它們是多執行緒通訊的基礎,而這種實現方式的思想自然是執行緒間通訊。

注意: wait和 notify必須配合synchronized使用,wait方法釋放鎖,notify方法不釋放鎖

58、synchronized 和 Lock 的區別和應用場景?

1、Lock 是介面,而 synchronized 是 Java 中的關鍵字,synchronized 是內建的語言實現;

2、synchronized 在發生異常時,會自動釋放執行緒佔有的鎖,因此不會導致死鎖現象發生;而 Lock 在發生異常時,如果沒有主動通過 unLock()去釋放鎖,則很可能造成死鎖現象,因此使用 Lock 時需要在 finally 塊中釋放鎖;

3、Lock 可以讓等待鎖的執行緒響應中斷,而 synchronized 卻不行,使用synchronized 時,等待的執行緒會一直等待下去,不能夠響應中斷;

4、通過 Lock 可以知道有沒有成功獲取鎖,而 synchronized 卻無法辦到。

5、Lock 可以提高多個執行緒進行讀操作的效率。

6、Lock 能完成 Synchronized 所實現的所有功能在效能上來說,如果競爭資源不激烈,Synchronized 要優於 Lock,而當競爭資源非常激烈時(即有大量執行緒同時競爭),此時 Lock 的效能要遠遠優於synchronized。所以說,在具體使用時要根據適當情況選擇。

59、為什麼要用執行緒池?

建立執行緒要花費昂貴的資源和時間,如果任務來了才建立執行緒那麼響應時間會變長,而且一個程式能建立的執行緒數 有限。為了避免這些問題,在程式啟動的時候就建立若干執行緒來響應處理,它們被稱為執行緒池,裡面的執行緒叫工作執行緒。從JDK1.5 開始,JavaAPI 提供了 Executor 框架讓你可以建立不同的執行緒池。比如單執行緒池,每次處理一個 任務;數目固定的執行緒池或者是快取執行緒池(一個適合很多生存期短的任務的程式的可擴充套件執行緒池)。

60、如何建立執行緒池?

1.執行緒池都是通過執行緒池工廠建立,再呼叫執行緒池中的方法獲取執行緒,再通過執行緒去執行任務方法。

Executors:執行緒池建立工廠類

2.自己根據建立執行緒池的需求來 new 物件(使用)

注意:執行緒池不允許使用 Executors 去建立,而是通過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同學更加明確執行緒池的執行規則,規避資源耗盡的風險。

說明:Executors 返回的執行緒池物件的弊端如下:

1)FixedThreadPool 和 SingleThreadPool:

允許的請求佇列長度為 Integer.MAX_VALUE,可能會堆積大量的請求,從而導致OOM。

2)CachedThreadPool 和 ScheduledThreadPool:

允許的建立執行緒數量為 Integer.MAX_VALUE,可能會建立大量的執行緒,從而導致 OOM。

建議自己通過 new 關鍵字建立 newThreadPoolExecutor

61、java中的異常體系?



62、throw 和 throws 的區別?

1、throws 用在函式上,後面跟的是異常類,可以跟多個;而 throw 用在函式內,後面跟的 是異常物件。

2、throws 用來宣告異常,讓呼叫者只知道該功能可能出現的問題,可以給出預先的處理方 式;throw 丟擲具體的問題物件,執行到 throw,功能就已經結束了,跳轉到呼叫者,並將具體的問題物件拋給呼叫者。也就是說 throw 語句獨立存在時,下面不要定義其他語句,因為執行不到。

3、throws 表示出現異常的一種可能性,並不一定會發生這些異常;throw則是丟擲了異常, 執行 throw 則一定 丟擲了某種異常物件。

4、兩者都是消極處理異常的方式,只是丟擲或者可能丟擲異常,但是不會由函式去處理異常,真正的處理異常由函式的上層呼叫處理。

63、說出 5 個常見的異常?

1、NullpointException:空指標異常 null 值 導致

2、IOExceptionIO 異常 IO 流常見編譯異常

3、SQLExceptionSQL 拼寫異常,mybatis 中的 sql 拼寫異常

4、ClassNotFoundException 類找不到異常 一般為 jar 包引入失敗或者忘寫 spring 註解

5、ClassCastException 型別轉換異常