一、java是一種什麼語言,jdk,jre,jvm三者的區別? java
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 語言寫做的軟件程序。c++
java SE java標準版
java EE java企業版
java ME java微型版spring
三、java跨平臺及其原理? sql
所謂的跨平臺就是java源碼通過一次編譯之後,能夠在不一樣的操做系統上運行
原理:通過編譯的 .class 文件運行在java虛擬機上,並不是直接運行在操做系統上,只要安裝知足不一樣操做系統的jvm便可。數據庫
一、面向對象。java 是面嚮對象語言,即知足面向對象的基本特徵(封裝,繼承,多態)。封裝是將 屬性,方法等放在一個類中,體現了java語言的安全性,繼承是子類繼承了父類後便有了父類的特性,多態則是父類的引用指向子類的地址,執行不一樣的操做,繼承和多態體現了java語言的靈活性,易擴展性。
二、跨平臺。jvm實現java語言的跨平臺。
三、支持網絡編程。
四、支持多線程。
五、健壯性。java語言的強類型機制,異常處理機制,GC垃圾自動收集機制。數組
字節碼:java 通過 javac 命令產生的 .class 文件就是字節碼。
字節碼的好處:一、在必定程度上解決了解釋性語言效率低下的問題。二、不針對特定的機器,保留了解釋性語言的可移植性。安全
java和c++都是面嚮對象語言。所以都有面向對象的基本特性封裝,繼承,多態。它們的區別以下:
一、java不提供指針來直接訪問內存,程序內存更加安全。
二、java中是單繼承,c++中支持多繼承。
三、java中有內存管理機制,無需程序員手動釋放內存。
封裝: 把方法、變量封裝在類中,提升代碼的安全性
繼承: java中爲單繼承,提升代碼的重用性
多態: 多態就是同一個類或者接口,使用不一樣的實例於是執行不一樣的操做,提升代碼的靈活性
說明 | 所佔內存大小(字節) | 取值範圍 | 默認值 | |
---|---|---|---|---|
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 |
類,接口類型,數組類型,枚舉類型,註解類型
基本數據類型在被建立時,會在棧上分配空間,直接將之存儲在棧中。而引用數據類型在被建立時,首先會在棧上分配空間,將其引用存在棧空間中,而後在堆中開闢內存,值存放在堆內存中,棧中的引用指向堆中的地址。
在java5之前,expr支持 byte,short,int,char 四種數據類型,在java5之後,又多了枚舉enum類型,java7又增長了string類型,到目前並比支持long類型。
十、int 和 Integer 有什麼區別,怎麼理解自動拆箱,自動裝箱?
int 是基本數據類型,默認值是0
integer是引用類型,是int 的包裝類,默認值是 null
自動拆箱:將包裝類型自動轉化爲對應的基本數據類型。
自動裝箱:將基本類型自動轉化爲對應的引用類型。
計算2^3效率最高的方法是:2<<(3-1)
四捨五入的原理是在原來的參數上加0.5,而後進行向下取整。
不正確。3.4是雙精度類型,賦值給float須要強制類型轉換,float f=(float)3.4,能夠寫成 float f=3.4F。
1四、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),存在隱含的強制類型轉換。
定義:註釋是用來解釋說明程序的文字。分爲:
單行註釋:// 註釋的文字
多行註釋:/* 註釋的文字 /
文檔註釋:/* 註釋的文字 **/
java中的訪問修飾符有:public,private,protected,以及不寫(默認)。
重寫: 至少發生在兩個類中,而且類與類具備繼承或者實現關係,表示子類中的方法具備與父類方法中徹底相同的方法名稱,返回值,參數。子類中的方法覆蓋父類的方法,體現了多態性。
重載: 發生在同一個類中,多個方法名稱相同,參數類型,個數和順序不一樣的方法發生重載現象,與返回值無關。
&:不管左邊true仍是false,右邊也會進行判斷。
&&:若是左邊爲false,有邊就不會進行判斷,所以&&比&效率高。
注意:邏輯或運算符(|)和短路或運算符(||)的差異也是如此。
goto 是 Java 中的保留字,在目前版本的 Java 中沒有使用。
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; } }
1.普通的直接引用。
2.調用父類中與子類重名的方法。
2.調用父類的構造函數。
在java中,final關鍵字能夠修飾類,變量和方法。被final修飾後如下特色:
final修飾類:final修飾的類不能被繼承。
final修飾變量:final修飾的變量是常量,不能改變。
final修飾方法:final修飾的方法不能被重寫。
2三、break ,continue ,return 的區別及做用?
break:跳出當前循環
continue:結束本次循環,進行下次循環
return:返回
在外面的循環語句前定義一個標號
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; } }
若是兩個對象equals()方法相等則它們的hashCode返回值必定要相同,若是兩個對象的hashCode返回值相同,但它們的equals()方法不必定相等。
兩個對象的hashCode()返回值相等不能判斷這兩個對象是相等的,但兩個對象的hashcode()返回值不相等則能夠斷定兩個對象必定不相等。
接口中的方法都是抽象的,抽象類中能夠有抽象方法,也能夠有非抽象方法。
在jdk1.8之後接口中也能夠有用defaule關鍵字修飾的普通方法
接口是一種規範,java中的接口:interface
靜態變量 | 非靜態變量 | |
---|---|---|
調用方式 | 靜態變量只能經過 「 類名.變量名 」 調用 | 非靜態變量經過實例化對象名調用 |
共享方式 | 靜態變量是全局變量,被類的全部實例化對象共享 | 非靜態變量是局部變量,不共享 |
相互訪問方式 | 靜態變量沒法訪問非靜態變量 | 非靜態變量能夠訪問靜態變量 |
值傳遞: 在方法的調用過程當中,實參把它的實際值傳遞給形參,此傳遞過程就是將實參的值複製一份傳遞到函數中。
引用傳遞: 引用傳遞彌補了值傳遞的不足,若是傳遞的數據量很大,直接復過去的話,會佔用大量的內存空間,而引用傳遞就是將對象的地址值傳遞過去,函數接收的是原始值的首地址值。在方法的執行過程當中,形參和實參的內容相同,指向同一塊內存地址,也就是說操做的其實都是源數據,因此方法的執行將會影響到實際對象。
JAVA 反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性。
方法 | 說明 |
---|---|
split() | 把字符串分割成字符串數組 |
indexOf() | 從指定字符提取索引位置 |
append() | 追加字符或字符串 |
trim() | 去掉字符串兩端的空格 |
replace() | 替換 |
hashCode() | 返回字符串的哈希值 |
subString() | 截取字符串 |
equals() | 比較字符串是否相等 |
length() | 獲取字符串長度 |
concat() | 將指定字符串鏈接到此字符串的結尾 |
"=="比較的是兩個字符串的內存地址。 "equals"比較的是兩個字符串的實際值
3三、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 : 字符串變量,非線程安全,用於單線程操做
3四、Java中final、finally和finalize的區別?
final: 修飾符,java 中的關鍵字。可用於修飾類,變量,方法,有最終的意思。
修飾的對象 | 說明 |
---|---|
final 修飾類 | 代表該類不能被其餘類所繼承,但要注意:final類中全部的成員方法都會隱式的定義爲final方法。 |
final 修飾變量 | final成員變量表示常量,只能被賦值一次,賦值後其值再也不改變 |
final 修飾方法 | final 修飾的方法不能被重寫 |
finally: finally 是在異常裏常常用到的, 就是 try 和 cach 裏的代碼執行完之後,必需要執行的方法,咱們常常在 finally 裏寫一些關閉資源的方法,好比說關閉數據庫鏈接,或者關閉 IO 流.
finalize: finalize是方法名,java技術容許使用finalize()方法在垃圾收集器將對象從內存中清除出去以前作必要的清理工做
java中不容許多繼承,好比類A不能同時繼承類B和類C,若要有次類需求,考慮用接口。
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()方法來判斷。
實現類 | 特徵 |
---|---|
HashMap | 線程不安全的鍵值對集合,容許 null 值,key 和 value 均可以 |
HashTable | 線程安全的鍵值對集合,不容許 null 值,key 和 value 都不能夠 |
TreeMap | 可以把它保存的記錄根據鍵排序,默認是按升序排序 |
- Collections.synchronizedMap() 方法
- java.util.concurrent.ConcurrentHashMap 類
在JDK1.6,JDK1.7中,HashMap採用位桶+鏈表實現,即便用鏈表處理衝突,同一hash值的鍵值對會被放在同一個位桶裏,當桶中元素較多時,經過key值查找的效率較低。
而JDK1.8中,HashMap採用位桶+鏈表+紅黑樹實現,當鏈表長度超過閾值(8),時,將鏈表轉換爲紅黑樹,這樣大大減小了查找時間。
當咱們建立 hashmap 時 會先建立一個數組,當咱們用 put 方法存數據時,先根據 key 的 hashcode 值計算出 hash 值,而後用這個哈希值肯定在數組中的位置,再把 value 值放進去,若是這個位置原本沒放 東西,就會直接放進去,若是以前就有,就會生成一個鏈表,把新放入的值放在頭部,當用 get 方法取值時,會先根據 key 的 hashcode 值計算出 hash 值,肯定位置,再根據 equals 方法從該位置上的鏈表中取出該 value 值。
對象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取值可能爲僞隨機數列。稱僞隨機探測再散列。
當發生衝突時,使用第二個、第三個、哈希函數計算地址,直到無衝突時。缺點:計算時間增長。好比上面第一次按照姓首字母進行哈希,若是產生衝突能夠按照姓字母首字母第二位進行哈希,再衝突,第三位,直到不衝突爲止。
將全部關鍵字爲同義詞的記錄存儲在同一線性鏈表中。以下:
當 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 的問題。
先獲取 Map 中的 key 的 set 集合 map.keySet(); 經過遍歷 key 集合,獲取 value 值。Map.get(key)先獲取 Entry 集合 map.entrySet(); 遍歷 entrySet 分別獲取 key value。
4三、 ArrayList 與 LinkedList 區別?
ArrayList 使用數組方式存儲數據,因此根據索引查詢數據速度快,而新增或者 刪除元素時須要設計到位移操做,因此比較慢。
LinkedList 使用雙向連接方式存儲數據,每一個元素都記錄先後元素的指針, 因此插入、刪除數據時只是更改先後元素的指針指向便可,速度很是快,而後經過下標查詢元素時須要從頭開始索引,因此比較慢,可是若是查詢前幾個元素或 後幾個元素速度比較快。
ArrayList 與 LinkedList 都是線程不安全的。
4四、 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
一、使用 Vector
二、使用 Collections 中的方法 synchronizedList 將 ArrayList 轉換爲線程安全的 List
三、使用 java.util.current 包下的 CopyOnWriteArrayList(推薦)
這個NIO是JDK1.7之後有的 ,它們倆的主要區別是 :io 是面向流是阻 塞 io,nio 是面向緩 衝,非阻塞的 io; io 話每次從流中讀取一 個多個字節 ,直到讀取完全部的字節 ,沒有緩存到 任何地方 .nio 讀取的是數據是有緩存 ,就是說他讀取的數據是 在緩衝裏讀的 . 另外的話 ,java 中的各類 io 是阻塞的 .就是說一個線程調用 read 或 者 write()時 ,這個線程就已經被阻塞了,直到讀取到一 些數據爲止 ,或者是徹底寫入。在這個過程當中不能幹其餘的事情 . nio 的非阻塞模式 ,當發送一個讀取數據的請求的時候 ,若是沒有讀取到可用的數據 ,就什麼也不會 獲取 ,且不會讓線程阻塞寫也是這樣。非阻塞的IO的空閒時間可用用來作其餘的操做因此,一個單 獨的非阻塞線 程能夠管理 多個輸入和輸出通道,另外 NIO 還有一 個 selector(選 擇 器 ),它是能夠管理多個輸入輸出的通道.
一種是繼承 Thread 類
另外一種就是實現 Runnable 接口
最後一種就是實現 Callable 接口
(第四種也是實現 callable 接口,只不過有返回值而已)
4八、Thread 類中的 start() 和 run() 方法有什麼區別?
start()方法被用來啓動新建立的線程,並且 start()內部調用了 run()方法,這和直接調用 run()方法的效果不同。當你調用 run()方法的時候,只會是在原來的線程中調用,沒有新的線程啓動,start()方法纔會啓動新線程。
4九、Java 中 notify 和 notifyAll 有什麼區別?
notify()方法不能喚醒某個具體的線程,因此只有一個線程在等待的時候它
纔有用武之地。而 notifyAll()喚醒全部線程並容許他們爭奪鎖確保了至少有一
個線程能繼續運行。
50、Java 多線程中調用 wait() 和 sleep()方法有什麼不一樣?
Java 程序中 wait 和 sleep 都會形成某種形式的暫停,它們能夠知足不一樣的須要。wait()方法用於線程間通訊,若是等待條件爲真且其它線程被喚醒時它會釋放鎖,而 sleep()方法僅僅釋放 CPU 資源或者讓當前線程中止執行一段時間,但不會釋放鎖。
多個線程同時運行一段代碼。若是每次運行結果和單線程運行的結果是同樣的,並且其餘的變量的值也和預期的是同樣的,就是線程安全的。同一個實例對象在被多個線程使用的狀況下也不會出現計算失誤,也是線程安全的,反之則是線程不安全的。
Volatile: 一個共享變量(類的成員變量、類的靜態成員量)被volatile修飾以後,那麼就具有了兩層語義:
a.保證了不一樣線程對這個變量進行操做時的可見性,即一個線程修改了某個變量的值,這新值對其餘線程來講是當即可見的。
b.禁止進行指令重排序。可是它並不能保證操做的原子性。
應用場景:在只涉及可見性,針對變量的操做只是簡單的讀寫(保證操做的
原子性)的狀況下可使用volatile來解決高併發問題,若是這時針對變量的操做是非原子的操做,這時若是隻是簡單的i++式的操做,可使用原子類atomic類來保證操做的原子性(採用CAS實現),若是是複雜的業務操做,那麼捨棄volatile,採用鎖來解決併發問題(synchronized或者Lock)。
實線程通常具備五種狀態,即建立、就緒、運行、阻塞、終止。
- 新建( 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 ()方法,則該線程結束生命週期。死亡的線程不可再次復生。
一、同步代碼塊:在代碼塊上加上「synchronized」關鍵字的話,則此代碼塊就稱爲同步代 碼塊。
同步代碼塊格式: synchronized(監視對象){ 須要同步的代碼 ; }
解釋:監視對象有三種:對象、String、.class 文件(只要是不變的對象均可以作監 視對象)
二、同步方法
同步方法定義格式: synchronized 方法返回值 方法名稱(參數列表){ } 在方法上加 synchronized,是把當前對象作爲監視器
三、同步鎖
Lock lock = new ReentrantLock();(能夠在類中直接 new) lock.lock(); 中間的代碼塊進行加鎖 lock.unlock();
- Synchronized
- Lock
Synchronized的侷限性:
1).若是這個獲取鎖的線程因爲要等待IO或者其餘緣由(好比調用sleep方法)被阻塞了,可是又沒有釋放鎖,其餘線程便只能乾巴巴地等待。(不能主動釋放鎖)
2).當有多個線程讀寫文件時,讀操做和寫操做會發生衝突現象,寫操做和寫操做會發生衝突現象,可是讀操做和讀操做不會發生衝突現象若是多個線程都只是進行讀操做,因此當一個線程在進行讀操做時,其餘線程只能等待沒法進行讀操做。(不分狀況,一概鎖死)
ReentrantLock是一個可重入的互斥鎖,又被稱爲「獨佔鎖」
ReadWriteLock,顧名思義,是讀寫鎖。它維護了一對相關的鎖 ——「讀取鎖」和「寫入鎖」,一個用於讀取操做,另外一個用於寫入操做。他的兩個實現類讀鎖readerLock和寫鎖writerLock。
一、使用 volatile 關鍵字。基於 volatile 關鍵字來實現線程間相互通訊是使用共享內存的思想,大體意思就是多個線程同時監聽一個變量,當這個變量發生變化的時候 ,線程可以感知並執行相應的業務。這也是最簡單的一種實現方式
二、使用Object類的wait() 和 notify() 方法。Object類提供了線程間通訊的方法:wait()、notify()、notifyaAl(),它們是多線程通訊的基礎,而這種實現方式的思想天然是線程間通訊。
注意: wait和 notify必須配合synchronized使用,wait方法釋放鎖,notify方法不釋放鎖
5八、synchronized 和 Lock 的區別和應用場景?
一、Lock 是接口,而 synchronized 是 Java 中的關鍵字,synchronized 是內置的語言實現;
二、synchronized 在發生異常時,會自動釋放線程佔有的鎖,所以不會致使死鎖現象發生;而 Lock 在發生異常時,若是沒有主動經過 unLock()去釋放鎖,則極可能形成死鎖現象,所以使用 Lock 時須要在 finally 塊中釋放鎖;
三、Lock 可讓等待鎖的線程響應中斷,而 synchronized 卻不行,使用synchronized 時,等待的線程會一直等待下去,不可以響應中斷;
四、經過 Lock 能夠知道有沒有成功獲取鎖,而 synchronized 卻沒法辦到。
五、Lock 能夠提升多個線程進行讀操做的效率。
六、Lock 能完成 Synchronized 所實現的全部功能在性能上來講,若是競爭資源不激烈,Synchronized 要優於 Lock,而當競爭資源很是激烈時(即有大量線程同時競爭),此時 Lock 的性能要遠遠優於synchronized。因此說,在具體使用時要根據適當狀況選擇。
建立線程要花費昂貴的資源和時間,若是任務來了才建立線程那麼響應時間會變長,並且一個進程能建立的線程數 有限。爲了不這些問題,在程序啓動的時候就建立若干線程來響應處理,它們被稱爲線程池,裏面的線程叫工做線程。從JDK1.5 開始,JavaAPI 提供了 Executor 框架讓你能夠建立不一樣的線程池。好比單線程池,每次處理一個 任務;數目固定的線程池或者是緩存線程池(一個適合不少生存期短的任務的程序的可擴展線程池)。
1.線程池都是經過線程池工廠建立,再調用線程池中的方法獲取線程,再經過線程去執行任務方法。
Executors:線程池建立工廠類
2.本身根據建立線程池的需求來 new 對象(使用)
注意:線程池不容許使用 Executors 去建立,而是經過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同窗更加明確線程池的運行規則,規避資源耗盡的風險。
說明:Executors 返回的線程池對象的弊端以下:
1)FixedThreadPool 和 SingleThreadPool:
容許的請求隊列長度爲 Integer.MAX_VALUE,可能會堆積大量的請求,從而致使OOM。
2)CachedThreadPool 和 ScheduledThreadPool:
容許的建立線程數量爲 Integer.MAX_VALUE,可能會建立大量的線程,從而致使 OOM。
建議本身經過 new 關鍵字建立 newThreadPoolExecutor
6一、java中的異常體系?
6二、throw 和 throws 的區別?
一、throws 用在函數上,後面跟的是異常類,能夠跟多個;而 throw 用在函數內,後面跟的 是異常對象。
二、throws 用來聲明異常,讓調用者只知道該功能可能出現的問題,能夠給出預先的處理方 式;throw 拋出具體的問題對象,執行到 throw,功能就已經結束了,跳轉到調用者,並將具體的問題對象拋給調用者。也就是說 throw 語句獨立存在時,下面不要定義其餘語句,由於執行不到。
三、throws 表示出現異常的一種可能性,並不必定會發生這些異常;throw則是拋出了異常, 執行 throw 則必定 拋出了某種異常對象。
四、二者都是消極處理異常的方式,只是拋出或者可能拋出異常,可是不會由函數去處理異常,真正的處理異常由函數的上層調用處理。
一、NullpointException:空指針異常 null 值 致使 二、IOExceptionIO 異常 IO 流常見編譯異常 三、SQLExceptionSQL 拼寫異常,mybatis 中的 sql 拼寫異常 四、ClassNotFoundException 類找不到異常 通常爲 jar 包引入失敗或者忘寫 spring 註解 五、ClassCastException 類型轉換異常