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介面的實作類,它們大體有一下幾個區別:
- 繼承的父類不同,HashMap是繼承自AbstractMap類,而HashTable是繼承自Dictionary類,
- 執行緒安全性不同,Hashtable 中的方法是Synchronize的,而HashMap中的方法在預設情況下是非Synchronize的,Hashtable 是現成安全的,HashMap是非執行緒安全的,
- 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 執行緒不安全問題?
- Collections.synchronizedMap() 方法
- 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、執行緒的狀態?
實執行緒一般具有五種狀態,即創建、就緒、運行、阻塞、終止,

- 新建( new ):新創建了一個執行緒物件,
- 可運行( runnable ):執行緒物件創建后,其他執行緒(比如 main 執行緒)呼叫了該物件的start ()方法,該狀態的執行緒位于可運行執行緒池中,等待被執行緒調度選中,獲 取 cpu 的使用權 ,
- 運行( running ):可運行狀態( runnable )的執行緒獲得了 cpu 時間片( timeslice ),執行程式代碼,
- 阻塞( 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 )狀態,- 死亡( 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中的鎖有幾種方式?
- Synchronized
- 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 型別轉換例外
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/3752.html
標籤:其他
