1. ?? ?JAVA中的幾種基本數(shù)據(jù)類型是什么,各自占用多少字節(jié)。?
類型占位取值范圍字節(jié)大小

==================================================================
2. ?? ?String類能被繼承嗎,為什么。?
public final class Stringimplements java.io.Serializable, Comparable, CharSequence
String 被final修飾了,所有不能被繼承。
1.final修飾的對(duì)象不能被修改;
2.final修飾的類不能被繼承;
3.final修飾的方法不能被重寫;
==================================================================
3. ?? ?String,Stringbuffer,StringBuilder的區(qū)別。
1.是否多線程安全
String對(duì)象因?yàn)槭遣豢勺兊模允蔷€程安全的;
StringBuffer對(duì)方法加了同步鎖或者對(duì)調(diào)用的方法加了同步鎖,所以是線程安全的;
StringBuilder非線程安全的。
2.可變與不可變
String類中使用字符數(shù)組保存字符串,如下就是,因?yàn)橛小癴inal”修飾符,所以可以知道string對(duì)象是不可變的。
?????????????? private final char value[];
StringBuffer和StringBuilder類中使用字符數(shù)組保存字符串,沒有使用final修飾,所以是可變的。
所以String對(duì)象進(jìn)行改變時(shí),是重新生成一個(gè)對(duì)象,并把引用指向新生成的對(duì)象,每次生成對(duì)象的時(shí)候都會(huì)浪費(fèi)性能,而且會(huì)產(chǎn)生很多的垃圾的中間對(duì)象,導(dǎo)致GC更加頻繁,StringBuffer和StringBuilder對(duì)象都是對(duì)對(duì)象本身進(jìn)行操作,不會(huì)改變對(duì)象的引用。所以普遍認(rèn)為當(dāng)字符串需要經(jīng)常進(jìn)行修改的情況下,String的性能比StringBuffer和StringBuilder低,但是也是有特例的:
public class Test{
public static void main(String[] args){
String string ="A"+"B"+"C";
StringBuffer stringBuffer = new StringBuffer("A").append("B").append("C");
StringBuilder stringBuilder = new StringBuilder("A").append("B").append("C");
}
}
1.這里面創(chuàng)建一個(gè)String 對(duì)象,JVM在編譯期進(jìn)行了常量折疊,直接拼接了ABC,所以在運(yùn)行的時(shí)候只進(jìn)行了兩步:從字符串常量池中獲取ABC、將string指向ABC
2.這里面創(chuàng)建一個(gè)StringBuffer和StringBuilder對(duì)象時(shí),都經(jīng)歷了七步:
a.從字符串常量池里面取出A,
b.調(diào)用StringBuilder和StringBuilder的append方法,添加A;
c.從字符串常量池里面取出B,
d.調(diào)用StringBuilder和StringBuilder的append方法,添加B;
e.從字符串常量池里面取出C,
f.調(diào)用StringBuilder和StringBuilder的append方法,添加C;
g.將?StringBuilder和StringBuilder指向?ABC
==================================================================
4. ?? ?ArrayList和LinkedList有什么區(qū)別。?
1.對(duì)ArrayList和LinkedList而言,在列表末尾增加一個(gè)元素所花的開銷都是固定的。對(duì)ArrayList而言,主要是在內(nèi)部數(shù)組中增加一項(xiàng),指向所添加的元素,偶爾可能會(huì)導(dǎo)致對(duì)數(shù)組重新進(jìn)行分配;而對(duì)LinkedList而言,這個(gè)開銷是統(tǒng)一的,分配一個(gè)內(nèi)部Entry對(duì)象。
2.在ArrayList的中間插入或刪除一個(gè)元素意味著這個(gè)列表中剩余的元素都會(huì)被移動(dòng);而在LinkedList的中間插入或刪除一個(gè)元素的開銷是固定的。
3.LinkedList不支持高效的隨機(jī)元素訪問。
4.ArrayList的空間浪費(fèi)主要體現(xiàn)在在list列表的結(jié)尾預(yù)留一定的容量空間,而LinkedList的空間花費(fèi)則體現(xiàn)在它的每一個(gè)元素都需要消耗相當(dāng)?shù)目臻g
可以這樣說:當(dāng)操作是在一列數(shù)據(jù)的后面添加數(shù)據(jù)而不是在前面或中間,并且需要隨機(jī)地訪問其中的元素時(shí),使用ArrayList會(huì)提供比較好的性能;當(dāng)你的操作是在一列數(shù)據(jù)的前面或中間添加或刪除數(shù)據(jù),并且按照順序訪問其中的元素時(shí),就應(yīng)該使用LinkedList了。
==================================================================
5.?? ?講講類的實(shí)例化順序,比如父類靜態(tài)數(shù)據(jù),父類構(gòu)造函數(shù),父類字段,子類靜態(tài)數(shù)據(jù),子類構(gòu)造函數(shù),子類字段,當(dāng)new的時(shí)候,他們的執(zhí)行順序。
類的實(shí)例化順序:先靜態(tài)再父子
父類靜態(tài)數(shù)據(jù)->子類靜態(tài)數(shù)據(jù)->父類字段->子類字段->父類構(gòu)造函數(shù)->子類構(gòu)造函數(shù)
==================================================================
6.?? ?用過哪些Map類,都有什么區(qū)別,HashMap是線程安全的嗎,并發(fā)下使用的Map是什么,他們內(nèi)部原理分別是什么,比如存儲(chǔ)方式,hashcode,擴(kuò)容,默認(rèn)容量等。
最常用的Map實(shí)現(xiàn)類有:HashMap,ConcurrentHashMap(jdk1.8),LinkedHashMap,TreeMap,HashTable;
其中最頻繁的是HashMap和ConcurrentHashMap,他們的主要區(qū)別是HashMap是非線程安全的。ConcurrentHashMap是線程安全的。
并發(fā)下可以使用ConcurrentHashMap和HashTable,他們的主要區(qū)別是:
1.ConcurrentHashMap的hash計(jì)算公式:(key.hascode()^ (key.hascode()>>> 16)) & 0x7FFFFFFF
?HashTable的hash計(jì)算公式:key.hascode()& 0x7FFFFFFF
2.HashTable存儲(chǔ)方式都是鏈表+數(shù)組,數(shù)組里面放的是當(dāng)前hash的第一個(gè)數(shù)據(jù),鏈表里面放的是hash沖突的數(shù)據(jù)
ConcurrentHashMap是數(shù)組+鏈表+紅黑樹
3.默認(rèn)容量都是16,負(fù)載因子是0.75。就是當(dāng)hashmap填充了75%的busket是就會(huì)擴(kuò)容,最小的可能性是(16*0.75),一般為原內(nèi)存的2倍
4.線程安全的保證:HashTable是在每個(gè)操作方法上面加了synchronized來達(dá)到線程安全,ConcurrentHashMap線程是使用CAS(compore and swap)來保證線程安全的
==================================================================
7.?? ?JAVA8的ConcurrentHashMap為什么放棄了分段鎖,有什么問題嗎,如果你來設(shè)計(jì),你如何設(shè)計(jì)。
jdk8 放棄了分段鎖而是用了Node鎖,減低鎖的粒度,提高性能,并使用CAS操作來確保Node的一些操作的原子性,取代了鎖。
但是ConcurrentHashMap的一些操作使用了synchronized鎖,而不是ReentrantLock,雖然說jdk8的synchronized的性能進(jìn)行了優(yōu)化,但是我覺得還是使用ReentrantLock鎖能更多的提高性能
==================================================================
8.?? 有順序的 Map 實(shí)現(xiàn)類?如果有,他們是怎么保證有序的 。?
順序的 Map 實(shí)現(xiàn)類:LinkedHashMap,TreeMap
LinkedHashMap 是基于元素進(jìn)入集合的順序或者被訪問的先后順序排序,TreeMap 則是基于元素的固有順序 (由 Comparator 或者 Comparable 確定)。
==================================================================
9.?? ?抽象類和接口的區(qū)別,類可以繼承多個(gè)類么,接口可以繼承多個(gè)接口么,類可以實(shí)現(xiàn)多個(gè)接口么。
抽象類和接口的區(qū)別:
1.抽象類可以有自己的實(shí)現(xiàn)方法,接口在jdk8以后也可以有自己的實(shí)現(xiàn)方法(default)
2.抽象類的抽象方法是由非抽象類的子類實(shí)現(xiàn),接口的抽象方法有接口的實(shí)現(xiàn)類實(shí)現(xiàn)
3.接口不能有私有的方法跟對(duì)象,抽象類可以有自己的私有的方法跟對(duì)象
類不可以繼承多個(gè)類,接口可以繼承多個(gè)接口,類可以實(shí)現(xiàn)多個(gè)接口
==================================================================
10.?? ?繼承和聚合的區(qū)別在哪。
繼承:指的是一個(gè)類(稱為子類、子接口)繼承另外的一個(gè)類(稱為父類、父接口)的功能,并可以增加它自己的新功能的能力,繼承是類與類或者接口與接口之間最常見的關(guān)系;在Java中此類關(guān)系通過關(guān)鍵字extends明確標(biāo)識(shí),在設(shè)計(jì)時(shí)一般沒有爭議性;
聚合:聚合是關(guān)聯(lián)關(guān)系的一種特例,他體現(xiàn)的是整體與部分、擁有的關(guān)系,即has-a的關(guān)系,此時(shí)整體與部分之間是可分離的,他們可以具有各自的生命周期,部分可以屬于多個(gè)整體對(duì)象,也可以為多個(gè)整體對(duì)象共享;比如計(jì)算機(jī)與CPU、公司與員工的關(guān)系等;表現(xiàn)在代碼層面,和關(guān)聯(lián)關(guān)系是一致的,只能從語義級(jí)別來區(qū)分;
==================================================================
11.?? ?講講你理解的nio。他和bio的區(qū)別是啥,談?wù)剅eactor模型。
BIO:同步阻塞式IO,服務(wù)器實(shí)現(xiàn)模式為一個(gè)連接一個(gè)線程,即客戶端有連接請(qǐng)求時(shí)服務(wù)器端就需要啟動(dòng)一個(gè)線程進(jìn)行處理,如果這個(gè)連接不做任何事情會(huì)造成不必要的線程開銷,當(dāng)然可以通過線程池機(jī)制改善。
NIO:同步非阻塞式IO,服務(wù)器實(shí)現(xiàn)模式為一個(gè)請(qǐng)求一個(gè)線程,即客戶端發(fā)送的連接請(qǐng)求都會(huì)注冊(cè)到多路復(fù)用器上,多路復(fù)用器輪詢到連接有I/O請(qǐng)求時(shí)才啟動(dòng)一個(gè)線程進(jìn)行處理。
reactor模型:反應(yīng)器模式(事件驅(qū)動(dòng)模式):當(dāng)一個(gè)主體發(fā)生改變時(shí),所有的屬體都得到通知,類似于觀察者模式。
==================================================================
12.?? ?反射的原理,反射創(chuàng)建類實(shí)例的三種方式是什么。
反射的原理:如果知道一個(gè)類的名稱/或者它的一個(gè)實(shí)例對(duì)象, 就能把這個(gè)類的所有方法和變量的信息(方法名,變量名,方法,修飾符,類型,方法參數(shù)等等所有信息)找出來。
反射創(chuàng)建類實(shí)例的三種方式:
1.Class.forName("com.A");
2.new A().getClass();
3.A.class;
==================================================================
13.?? ?反射中,Class.forName和ClassLoader區(qū)別。
class.forName()除了將類的.class文件加載到j(luò)vm中之外,還會(huì)對(duì)類進(jìn)行解釋,執(zhí)行類中的static塊。
classLoader只干一件事情,就是將.class文件加載到j(luò)vm中,不會(huì)執(zhí)行static中的內(nèi)容,只有在newInstance才會(huì)去執(zhí)行static塊。
==================================================================
Java的動(dòng)態(tài)代理(dynamic proxy)
什么是動(dòng)態(tài)代理(dynamic proxy)
動(dòng)態(tài)代理(以下稱代理),利用Java的反射技術(shù)(Java Reflection),在運(yùn)行時(shí)創(chuàng)建一個(gè)實(shí)現(xiàn)某些給定接口的新類(也稱“動(dòng)態(tài)代理類”)及其實(shí)例(對(duì)象)
(Using Java Reflection to create dynamic implementations of interfaces at runtime)。
代理的是接口(Interfaces),不是類(Class),更不是抽象類。
動(dòng)態(tài)代理有什么用
解決特定問題:一個(gè)接口的實(shí)現(xiàn)在編譯時(shí)無法知道,需要在運(yùn)行時(shí)才能實(shí)現(xiàn)
實(shí)現(xiàn)某些設(shè)計(jì)模式:適配器(Adapter)或修飾器(Decorator)
面向切面編程:如AOP in Spring
14.?? ?描述動(dòng)態(tài)代理的幾種實(shí)現(xiàn)方式,分別說出相應(yīng)的優(yōu)缺點(diǎn)。
動(dòng)態(tài)代理有兩種實(shí)現(xiàn)方式,分別是:jdk動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理
jdk動(dòng)態(tài)代理的前提是目標(biāo)類必須實(shí)現(xiàn)一個(gè)接口,代理對(duì)象跟目標(biāo)類實(shí)現(xiàn)一個(gè)接口,從而避過虛擬機(jī)的校驗(yàn)。
cglib動(dòng)態(tài)代理是繼承并重寫目標(biāo)類,所以目標(biāo)類和方法不能被聲明成final。
==================================================================
15.?? ?動(dòng)態(tài)代理與cglib實(shí)現(xiàn)的區(qū)別。
動(dòng)態(tài)代理有兩種實(shí)現(xiàn)方式,分別是:jdk動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理
jdk動(dòng)態(tài)代理的前提是目標(biāo)類必須實(shí)現(xiàn)一個(gè)接口,代理對(duì)象跟目標(biāo)類實(shí)現(xiàn)一個(gè)接口,從而避過虛擬機(jī)的校驗(yàn)。
cglib動(dòng)態(tài)代理是繼承并重寫目標(biāo)類,所以目標(biāo)類和方法不能被聲明成final。
==================================================================
16.?? ?為什么cglib方式可以對(duì)接口實(shí)現(xiàn)代理。
cglib動(dòng)態(tài)代理是繼承并重寫目標(biāo)類,所以目標(biāo)類和方法不能被聲明成final。而接口是可以被繼承的。
==================================================================
17.?? ?final的用途。
1.final修飾的對(duì)象不能被修改;
2.final修飾的類不能被繼承;
3.final修飾的方法不能被重寫;
==================================================================
18.?? ?寫出三種單例模式實(shí)現(xiàn)。
?餓漢式
public class Singleton1 {
??? /*
??? * 餓漢式是在聲明的時(shí)候就已經(jīng)初始化Singleton1,確保了對(duì)象的唯一性
??? *
??? * 聲明的時(shí)候就初始化對(duì)象會(huì)浪費(fèi)不必要的資源
??? * */
??? private static Singleton1 instance = new Singleton1();
??? private Singleton1() {
??? }
??? // 通過靜態(tài)方法或枚舉返回單例對(duì)象
??? public Singleton1 getInstance() {
??????? return instance;
??? }
}
懶漢式
public class Singleton2 {
??? private static Singleton2 instance;
??? private Singleton2() {
??? }
??? /*
??? * getInstance 添加了synchronized 關(guān)鍵字,,也就是說 getInstance 是一個(gè)同步方法,
??? * 這就是懶漢式在多線程中保持唯一性的方式
??? *
??? * 懶漢式存在的問題是,即是instance已經(jīng)被創(chuàng)建,每次調(diào)用getInstance方法還是會(huì)同步,這樣就會(huì)浪費(fèi)一些不必要的資源
??? * */
??? public static synchronized Singleton2 getInstance() {
??????? if (instance == null) {
??????????? instance = new Singleton2();
??????? }
??????? return instance;
??? }
}
==================================================================
19.?? ?如何在父類中為子類自動(dòng)完成所有的hashcode和equals實(shí)現(xiàn)?這么做有何優(yōu)劣。
父類的equals不一定滿足子類的equals需求。比如所有的對(duì)象都繼承Object,默認(rèn)使用的是Object的equals方法,在比較兩個(gè)對(duì)象的時(shí)候,是看他們是否指向同一個(gè)地址。
但是我們的需求是對(duì)象的某個(gè)屬性相同,就相等了,而默認(rèn)的equals方法滿足不了當(dāng)前的需求,所以我們要重寫equals方法。
如果重寫了equals 方法就必須重寫hashcode方法,否則就會(huì)降低map等集合的索引速度。
==================================================================
20.?? ?請(qǐng)結(jié)合OO設(shè)計(jì)理念,談?wù)勗L問修飾符public、private、protected、default在應(yīng)用設(shè)計(jì)中的作用。
OO設(shè)計(jì)理念:封裝、繼承、多態(tài)
封裝,也就是把客觀事物封裝成抽象的類,并且類可以把自己的數(shù)據(jù)和方法只讓可信的類或者對(duì)象操作,對(duì)不可信的進(jìn)行信息隱藏。所以我們可以通過public、private、protected、default 來進(jìn)行訪問控制
關(guān)鍵字類內(nèi)部本包子類外部包
public?√√√√
protected√√√×
default?√√××
private√×××
java訪問控制符的含義和使用情況
==================================================================?
21.?? ?深拷貝和淺拷貝區(qū)別。
淺拷貝只拷貝指針,深拷貝就是拷貝他的值,重新生成的對(duì)像。
==================================================================
22.?? ?數(shù)組和鏈表數(shù)據(jù)結(jié)構(gòu)描述,各自的時(shí)間復(fù)雜度。
數(shù)組是將元素在內(nèi)存中連續(xù)存放,由于每個(gè)元素占用內(nèi)存相同,可以通過下標(biāo)迅速訪問數(shù)組中任何元素。
鏈表恰好相反,鏈表中的元素在內(nèi)存中不是順序存儲(chǔ)的,而是通過存在元素中的指針聯(lián)系到一起。
訪問數(shù)組中第 n 個(gè)數(shù)據(jù)的時(shí)間花費(fèi)是 O(1) 但是要在數(shù)組中查找一個(gè)指定的數(shù)據(jù)則是 O(N) 。當(dāng)向數(shù)組中插入或者刪除數(shù)據(jù)的時(shí)候,最好的情況是在數(shù)組的末尾進(jìn)行操作,時(shí)間復(fù)雜度是 O(1) ,但是最壞情況是插入或者刪除第一個(gè)數(shù)據(jù),時(shí)間復(fù)雜度是 O(N) 。在數(shù)組的任意位置插入或者刪除數(shù)據(jù)的時(shí)候,后面的數(shù)據(jù)全部需要移動(dòng),移動(dòng)的數(shù)據(jù)還是和數(shù)據(jù)個(gè)數(shù)有關(guān)所以總體的時(shí)間復(fù)雜度仍然是 O(N) 。?
?在鏈表中查找第 n 個(gè)數(shù)據(jù)以及查找指定的數(shù)據(jù)的時(shí)間復(fù)雜度是 O(N) ,但是插入和刪除數(shù)據(jù)的時(shí)間復(fù)雜度是 O(1)
==================================================================
23.?? ?error和exception的區(qū)別,CheckedException,RuntimeException的區(qū)別。
Error(錯(cuò)誤)表示系統(tǒng)級(jí)的錯(cuò)誤和程序不必處理的異常,是java運(yùn)行環(huán)境中的內(nèi)部錯(cuò)誤或者硬件問題。比如:內(nèi)存資源不足等。對(duì)于這種錯(cuò)誤,程序基本無能為力,除了退出運(yùn)行外別無選擇,它是由Java虛擬機(jī)拋出的。
Exception(違例)表示需要捕捉或者需要程序進(jìn)行處理的異常,它處理的是因?yàn)槌绦蛟O(shè)計(jì)的瑕疵而引起的問題或者在外的輸入等引起的一般性問題,是程序必須處理的。
Exception又分為運(yùn)行時(shí)異常,受檢查異常。
RuntimeException(運(yùn)行時(shí)異常),表示無法讓程序恢復(fù)的異常,導(dǎo)致的原因通常是因?yàn)閳?zhí)行了錯(cuò)誤的操作,建議終止程序,因此,編譯器不檢查這些異常。
CheckedException(受檢查異常),是表示程序可以處理的異常,也即表示程序可以修復(fù)(由程序自己接受異常并且做出處理), 所以稱之為受檢查異常。
==================================================================
24.?? ?請(qǐng)列出5個(gè)運(yùn)行時(shí)異常。
NullPointerException
IndexOutOfBoundsException
ClassCastException
ArrayStoreException
BufferOverflowException
==================================================================
25.?? ?在自己的代碼中,如果創(chuàng)建一個(gè)java.lang.String對(duì)象,這個(gè)對(duì)象是否可以被類加載器加載?為什么。
不可以,雙親委派模式會(huì)保證父類加載器先加載類,就是BootStrap(啟動(dòng)類)加載器加載jdk里面的java.lang.String類,而自定義的java.lang.String類永遠(yuǎn)不會(huì)被加載到
==================================================================
26.?? ?說一說你對(duì)java.lang.Object對(duì)象中hashCode和equals方法的理解。在什么場景下需要重新實(shí)現(xiàn)這兩個(gè)方法。
父類的equals不一定滿足子類的equals需求。比如所有的對(duì)象都繼承Object,默認(rèn)使用的是Object的equals方法,在比較兩個(gè)對(duì)象的時(shí)候,是看他們是否指向同一個(gè)地址。
但是我們的需求是對(duì)象的某個(gè)屬性相同,就相等了,而默認(rèn)的equals方法滿足不了當(dāng)前的需求,所以我們要重寫equals方法。
如果重寫了equals 方法就必須重寫hashcode方法,否則就會(huì)降低map等集合的索引速度。
==================================================================
27.?? ?在jdk1.5中,引入了泛型,泛型的存在是用來解決什么問題。
泛型的好處是在編譯的時(shí)候檢查類型安全,并且所有的強(qiáng)制轉(zhuǎn)換都是自動(dòng)和隱式的,提高代碼的重用率。
==================================================================
28.??? 有沒可能 2個(gè)不相等的對(duì)象有同hashcode。
有可能,最簡單的方法,百分百實(shí)現(xiàn)的方式就是重寫hascode();
==================================================================
29.??? Java中的HashSet內(nèi)部是如何工作的。
public HashSet() {map =new HashMap<>();}
默認(rèn)使用的是HaseMap;
==================================================================
30.??? 什么是序列化,怎么序列化,為什么序列化,反序列化會(huì)遇到什么問題,如何解決。
序列化是一種用來處理對(duì)象流的機(jī)制 ,所謂對(duì)象流就是將對(duì)象的內(nèi)容進(jìn)行流化。
序列化是為了解決在對(duì)對(duì)象流進(jìn)行讀寫操作時(shí)所引發(fā)的問題。
序列化的實(shí)現(xiàn):將需要被序列化的類實(shí)現(xiàn)Serializable接口,該接口沒有需要實(shí)現(xiàn)的方法,implements Serializable只是為了標(biāo)注該對(duì)象是可被序列化的,然后使用一個(gè)輸出流(如:FileOutputStream)來構(gòu)造一個(gè)ObjectOutputStream(對(duì)象流)對(duì)象,接著,使用ObjectOutputStream對(duì)象的writeObject(Object obj)方法就可以將參數(shù)為obj的對(duì)象寫出(即保存其狀態(tài)),要恢復(fù)的話則用輸入流;
線程池的作用:
線程池作用就是限制系統(tǒng)中執(zhí)行線程的數(shù)量。
根 據(jù)系統(tǒng)的環(huán)境情況,可以自動(dòng)或手動(dòng)設(shè)置線程數(shù)量,達(dá)到運(yùn)行的最佳效果;少了浪費(fèi)了系統(tǒng)資源,多了造成系統(tǒng)擁擠效率不高。用線程池控制線程數(shù)量,其他線程排 隊(duì)等候。一個(gè)任務(wù)執(zhí)行完畢,再從隊(duì)列的中取最前面的任務(wù)開始執(zhí)行。若隊(duì)列中沒有等待進(jìn)程,線程池的這一資源處于等待。當(dāng)一個(gè)新任務(wù)需要運(yùn)行時(shí),如果線程池 中有等待的工作線程,就可以開始運(yùn)行了;否則進(jìn)入等待隊(duì)列。
為什么要用線程池:
1.減少了創(chuàng)建和銷毀線程的次數(shù),每個(gè)工作線程都可以被重復(fù)利用,可執(zhí)行多個(gè)任務(wù)。
2.可以根據(jù)系統(tǒng)的承受能力,調(diào)整線程池中工作線線程的數(shù)目,防止因?yàn)橄倪^多的內(nèi)存,而把服務(wù)器累趴下(每個(gè)線程需要大約1MB內(nèi)存,線程開的越多,消耗的內(nèi)存也就越大,最后死機(jī))。
Java里面線程池的頂級(jí)接口是Executor,但是嚴(yán)格意義上講Executor并不是一個(gè)線程池,而只是一個(gè)執(zhí)行線程的工具。真正的線程池接口是ExecutorService。
比較重要的幾個(gè)類:
ExecutorService: 真正的線程池接口。
ScheduledExecutorService: 能和Timer/TimerTask類似,解決那些需要任務(wù)重復(fù)執(zhí)行的問題。
ThreadPoolExecutor: ExecutorService的默認(rèn)實(shí)現(xiàn)。
ScheduledThreadPoolExecutor: 繼承ThreadPoolExecutor的ScheduledExecutorService接口實(shí)現(xiàn),周期性任務(wù)調(diào)度的類實(shí)現(xiàn)。
要配置一個(gè)線程池是比較復(fù)雜的,尤其是對(duì)于線程池的原理不是很清楚的情況下,很有可能配置的線程池不是較優(yōu)的,因此在Executors類里面提供了一些靜態(tài)工廠,生成一些常用的線程池。