題目整理
Java基礎進階階段
基礎概念類
1.JDK1.8新特性?html
2.面向對象和麪向過程的區別?java
3.什麼是值傳遞和引用傳遞?mysql
4.什麼是不可變對象?程序員
5.講講類的實例化順序?web
6.java 建立對象的幾種方式算法
7.Java訪問修飾符的做用域sql
8.switch中可否使用string做爲參數?數據庫
9.switch中可否做用在byte,long上?編程
10.什麼是自動拆裝箱?設計模式
11.如何正確的退出多層嵌套循環?
繼承
1.Java支持多繼承麼?
2.父類的靜態方法可否被子類重寫?
3.繼承的好處和壞處?
接口抽象類
1.接口的意義?
2.抽象類的意義?
3.抽 象 的 (abstract) 方 法 是 否 可 同 時 是 靜 態 的 (static), 是 否 可 同 時 是 本 地 方 法(native)?
4.抽象類和接口區別?
5.Java中接口可不能夠繼承通常類,爲何?
6.重載與重寫區別?
7.final有哪些用法?
多態
1.多態的好處和弊端?
2.代碼中如何實現多態?
3.Java 中實現多態的機制是什麼?
內部類Lambda
1.內部類的做用?
2.一個java文件內部能夠有類?(非內部類)
3.Lambda的使用前提是什麼?
4.Lambda與匿名內部類區別?
static關鍵字
1.是否能夠在static環境中訪問非static變量?
2.static都有哪些用法?
3.靜態變量和實例變量的區別?
4.static特色?
數據類型
1.String s1=」ab」, String s2=」a」+」b」, String s3=」a」, String s4=」b」, s5=s3+s4請問s5==s2返回什麼?
2.3*0.1==0.3返回值是什麼?
3.基本數據類型的默認值?基本數據類型所佔的字節以及封裝他們的類?
4.String屬於那個類,以及經常使用的方法?
5.String, StringBuffer和StringBuilder區別?
異常類
1.error和exception有什麼區別?
2.運行時異常和通常異常有何不一樣?
3.Java中異常處理機制的原理?
4.你平時在項目中是怎樣對異常進行處理的?
5.throw和throws有什麼區別?
6.異常處理的時候,finally代碼塊的重要性是什麼?
7.請列出 5 個運行時異常?
8.try catch finally,try裏有return,finally還執行麼?
集合
一、List、Map、Set三個接口,存取元素時,各有什麼特色?
二、ArrayList和LinkedList的底層實現原理?他們爲何線程不安全?在多線程併發操做下,咱們應該用什麼替代?
三、HashMap和HashTable有什麼區別?其底層實現是什麼?CurrentHashMap的鎖機制又是如何?若是想將一個Map變爲有序的,該如何實現?
4.什麼是迭代器(Iterator)?
5.Arraylist 與 LinkedList 區別?
6.Arraylist 與 LinkedList 應用場景?
7.Collection 和 Collections的區別?
8.爲什麼Map接口不繼承Collection接口?
9.當兩個對象的hashcode相同會發生什麼?
10.HashMap和Hashtable有什麼區別?
11.List 和 Set 區別?
12.Set和List對比?
13.當兩個對象的hashcode相同會發生什麼?
14.若是兩個鍵的hashcode相同,你如何獲取值對象?
15.有沒有可能兩個不相等的對象有相同的hashcode?
16.HashMap、LinkedHashMap、TreeMap的區別?
17.HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底層實現。
18.==和 equals hashCode 的區別?
19.天然排序Comparble和比較器排序Comparator的異同點?
泛型
1.爲何使用泛型?
2.泛型用在什麼地方?
3.如何使用泛型類?
樹
1.什麼是二叉樹?
2.什麼是二叉查找樹?
3.什麼是平衡二叉樹?
序列化
1.什麼是 Java 序列化?
2.如何實現 Java 序列化?
3.Java 序列話中,若是有些字段不想進行序列化怎麼辦?
4.對象操做流是字符流仍是字節流?
5.如何在讀寫文件時指定字符集?
6.字符緩衝流特有方法?
7.爲何使用對象流?
多線程
1.什麼是線程?
2.線程和進程有什麼區別?
3.如何在Java中實現線程?
4.用Runnable仍是Thread?
5.Thread 類中的start() 和 run() 方法有什麼區別?
6.Java中Runnable和Callable有什麼不一樣?
7.Java內存模型是什麼?
8.Java中的volatile 變量是什麼?
9.什麼是線程安全?Vector是一個線程安全類嗎?
10.Java中如何中止一個線程?
11.Java中notify 和 notifyAll有什麼區別?
12. 什麼是線程池? 爲何要使用它?
13.如何寫代碼來解決生產者消費者問題?
14.Java多線程中的死鎖?
15.Java中synchronized 和 ReentrantLock 有什麼不一樣?
16.詳談Synchronized?
17.在Java中Lock接口與synchronized塊的區別是什麼?
18.synchronized 的原理是什麼?有什麼不足?
19.關於成員變量和局部變量?
20. 若是你提交任務時,線程池隊列已滿。會時發會生什麼?
21.volatile關鍵字的做用是?
22.守護線程和非守護線程有什麼區別?
23.線程的生命週期?
24.wait和sleep,notify()鎖方面區別?
25.什麼狀況下會出現線程安全問題?
26.Java中規定了線程有哪幾種狀態?
27.什麼是原子性?
28.Java中哪些操做是原子操做?
29.什麼是CAS算法?
30.synchronized和CAS的區別?
31.併發容器Hashtable和ConcurrentHashMap特色?
反射
1.Java反射機制的做用?
2.什麼是反射機制?
3.哪裏用到反射機制?
4.反射機制的優缺點?
5.反射中,Class.forName 和 ClassLoader 區別
6.什麼是雙親委派模型?
7.爲何要有雙親委派模型?
8.怎麼利用反射使用私有成員?
網絡通訊
1.什麼是三次握手?
2.什麼是四次揮手?
3.TCP通訊注意事項?
web階段
jsp相關
1.jsp內置對象和EL內置對象的區別與聯繫?
2.說一下 jsp 的 4 種做用域?
3.ServletContext 與application的異同?
4.jsp 有哪些內置對象?做用分別是什麼?
概念相關
1.post和get區別?
2.簡單闡述相對路徑和絕對路徑?
3.Cookie和session的區別?
4.servlet四大域對象的區別?
5.什麼是活化與鈍化?
6.EL內置對象有哪些?
7.若是有大量的網站訪問量。那麼會產生不少的session,該怎麼解決?
8.頁面傳遞對象的方法?
9.session 和 application的區別?
servlet相關
1.解釋一下什麼是servlet?
2.servlet的生命週期?
3.servlet生命週期方法有哪些?
4.servlet過濾器的做用?
5.servlet監聽器的做用?
6.web.xml中組件的加載順序?
7.如何確保servlet在應用啓動以後被加載到內存?
8.HttpServlet爲何聲明爲抽象類?
9.redirect(重定向)和forward(請求轉發)區別?
10.sevlet中的屬性域有哪些?
11.Servlet是否線程安全?
12.如何建立線程安全的servlet?(SingleThreadModel方法不算)
13.是否有必要重寫service方法?
14.servlet包裝類有什麼用?
15.在servlet中可否產生相似死鎖狀況?
16.Servlet API中forward()與redirect()的區別?
17.ServletContext對象和ServletConfig對象的區別?
18.PrintWriter和ServletOutPutStream類有什麼區別?
19.在一個servlet可否同時獲取PrintWriter和ServletOutputStream對象?
20.Request對象的主要方法有哪些?
21.jsp和servlet的異同點以及聯繫是什麼?
數據庫階段
索引相關
1.什麼是索引?
2.索引是個什麼樣的數據結構呢?
3.在創建索引的時候,都有哪些須要考慮的因素呢?
4.關心過業務系統裏面的sql耗時嗎?統計過慢查詢嗎?對慢查詢都怎麼優化過?
5.區別B樹,B-,B+,B*?
6.MySQL優化策略?
7.key和index的區別?
8.怎麼驗證 mysql 的索引是否知足需求?
事務相關
1.ACID是什麼?能夠詳細說一下嗎?
2.同時有多個事務在進行會怎麼樣呢?
3.怎麼解決這些問題呢?MySQL的事務隔離級別瞭解嗎?
4.Innodb使用的是哪一種隔離級別呢?
5.對MySQL的鎖瞭解嗎?
6.MySQL都有哪些鎖呢?像上面那樣子進行鎖定豈不是有點阻礙併發效率了?
7.行級鎖定的優勢缺點?
8.說一下 mysql 的行鎖和表鎖?
表設計相關
1. 爲何要儘可能設定一個主鍵?
2.主鍵使用自增ID仍是UUID?
3. 字段爲何要求定義爲not null?
4.varchar(10)和int(10)表明什麼含義?
5.建表策略?
存儲引擎相關
1. MySQL支持哪些存儲引擎?
2.InnoDB和MyISAM有什麼區別?
3.什麼是存儲過程?有哪些優缺點?
4.說一說三個範式?
答案整理
Java基礎進階階段
基礎概念類
1.JDK1.8新特性?
提供lambda表達式極大地減小了代碼的冗餘; 在接口中能夠使用default和static關鍵字來修飾接口中的普通方法; 提供新的API LocalDate | LocalTime | LocalDateTime
- Java.util.Date和SimpleDateFormatter線程上都不安全,而LocalDate和LocalTime和 String同樣都是不可改變類,線程上比較安全,還不能修改;
- Java.util.Date月份從0開始,12月是11,而java.time.LocalDate月份和星期都改爲了 enum, 就不可能出錯了;
2.面向對象和麪向過程的區別?
面向過程
- 優勢:性能比面向對象高,由於類調用時須要實例化,開銷比較大,比較消耗資源。好比,單片機、嵌入式開發、Linux/Unix 等通常採用面向過程開發,性能是最重要的因素。
- 缺點:沒有面向對象易維護、易複用、易擴展。
面向對象
- 優勢:易維護、易複用、易擴展,因爲面向對象有封裝、繼承、多態性的特性,能夠設計出低耦合的系統,使系統更加靈活、更加易於維護。
- 缺點:性能比面向過程低。
3.什麼是值傳遞和引用傳遞?
- 值傳遞,是對基本型變量而言的,傳遞的是該變量的一個副本,改變副本不影響原變量。
- 引用傳遞,通常是對於對象型變量而言的,傳遞的是該對象地址的一個副本,並非原對象自己。
通常認爲,Java 內的傳遞都是值傳遞,Java 中實例對象的傳遞是引用傳遞。
4.什麼是不可變對象
- 不可變對象指對象一旦被建立,狀態就不能再改變。任何修改都會建立一個新的對象,如 String、Integer及其它包裝類。
5.講講類的實例化順序?
初始化順序以下:
- 父類靜態變量
- 父類靜態代碼塊
- 子類靜態變量、
- 子類靜態代碼塊
- 父類非靜態變量(父類實例成員變量)
- 父類構造函數
- 子類非靜態變量(子類實例成員變量)
- 子類構造函數
6.java 建立對象的幾種方式
- 採用new
- 經過反射
- 採用clone
- 經過序列化機制
前2者都須要顯式地調用構造方法。形成耦合性最高的剛好是第一種,所以你發現不管什麼框架,只要涉及到解耦必先減小new的使用
7.Java訪問修飾符的做用域
做用域 當前類 同包 子類 其它
- public Y Y Y Y
- protected Y Y Y N
- default Y Y N N
- private Y N N N
8.switch中可否使用string做爲參數?
- 在jdk1.7以前,switch只能支持byte,short,char,int或者其餘對應的封裝類以及Enum類型.jdk1.7以後開始支持String
9.switch中可否做用在byte,long上?
10.什麼是自動拆裝箱?
- 自動裝箱和拆箱,就是基本類型和引用類型之間的轉換。
- 把基本數據類型轉換成包裝類的過程就是打包裝,爲裝箱。
- 把包裝類轉換成基本數據類型的過程就是拆包裝,爲拆箱。
11.如何正確的退出多層嵌套循環?
使用標號和break;
繼承
-
Java支持多繼承麼?
- Java類中不支持多繼承,可是能夠多實現,因此接口的擴展性比較好,實際開發中儘可能避免繼承的使用
-
父類的靜態方法可否被子類重寫
- 不能。重寫只適用於實例方法,不能用於靜態方法,而子類當中含有和父類相同簽名的靜態方法,咱們通常稱之爲隱藏。
-
繼承的好處和壞處
- 好處:
- 子類能自動繼承父類的對象 二、建立子類的對象時,無須建立父類的對象
- 壞處:
- 破壞封裝,子類與父類之間緊密耦合,子類依賴於父類的實現,子類缺少獨立性。
- 支持擴展,可是每每以加強系統結構的複雜度爲代價
- 不支持動態繼承。在運行時,子類沒法選擇不一樣的父類
- 子類不能改變父類的接口
接口抽象類
1.接口的意義
2.抽象類的意義
- 爲其餘子類提供一個公共的類型
- 封裝子類中重複定義的內容
- 定義抽象方法,子類雖然有不一樣的實現,可是定義時一致的
3.抽 象 的 (abstract) 方 法 是 否 可 同 時 是 靜 態 的 (static), 是 否 可 同 時 是 本 地 方 法(native)
- abstract關鍵字不能同時與static或private或final同時修飾一個方法;
4.抽象類和接口區別?
-
語法區別:
-
抽象類能夠有構造方法,接口不能有構造方法
-
抽象類中能夠有普通成員變量,接口中沒有普通成員變量;
-
抽象類中能夠有非抽象的方法,接口中的方法都必須是抽象的;
-
抽象類中的方法能夠是public,protected類型,接口中的方法只能是public類型的,切 默認爲public abstract類型;
-
抽象類中能夠有靜態方法,接口中不能有靜態方法;
-
抽象類中的靜態變量訪問類型能夠是任意的,但接口中的靜態變量只能是public static final 類型。
-
.一個類能夠實現多個接口,但一個類只能繼承一個抽象類;
-
應用區別:
5.Java中接口可不能夠繼承通常類,爲何?
不能夠由於接口中只能出現3種成員:
而一個類中,就算什麼都不寫,也必須帶一個構造方法,在extends時就會被子類繼承,若是是接口也會 繼承這個構造方法,很明顯構造方法不在上面三項之列 而若是類中有通常的方法和成員變量,也會被子類所有繼承,這些更不能出如今接口中了,因此接口是絕 對不可能繼承一個類的
6.重載與重寫區別
override(重寫)
- 方法名、參數、返回值相同。
- 子類方法不能縮小父類方法的訪問權限。
- 子類方法不能拋出比父類方法更多的異常(但子類方法能夠不拋出異常)。
- 存在於父類和子類之間。
- 被final修飾的方法,不能被重寫。
overload(重載)
- 參數類型、個數、順序至少有一個不相同。
- 不能重載只有返回值不一樣的方法名。
- 存在於父類和子類、同類中。
7.final有哪些用法?
- 被final修飾的類不能夠被繼承
- 被final修飾的方法不能夠被重寫
- 被final修飾的變量不能夠被改變。若是修飾引用,那麼表示引用不可變,引用指向的內容可變。
注:修飾變量, final 數據類型 變量名=數據值; 若是該變量是基本數據類型,則值不能修改,若是該變量是引用數據類型,則地址值不能改(既只能new一次);
- 被final修飾的方法,JVM會嘗試將其內聯,以提升運行效率
- 被final修飾的常量,在編譯階段會存入常量池中。
回答出編譯器對final域要遵照的兩個重排序規則更好:
- 在構造函數內對一個final域的寫入,與隨後把這個被構造對象的引用賦值給一個引用變量,這兩個操做之間不能重排序。
- 初次讀一個包含final域的對象的引用,與隨後初次讀這個final域,這兩個操做之間不能重排序。
多態
1.多態的好處和弊端
許不一樣類對象對同一消息作出響應,即同一消息能夠根據發送對象的不一樣而採用多種不一樣的行爲方式(發送消息就是函數調用)。即父類型的引用指向子類型的對象。
- 優勢:
- 可替換性:多態對已存在代碼具備可替換性
- 可擴充性:增長新的子類不影響已經存在的類結構
- 更加靈活
- 弊端:
2.代碼中如何實現多態
實現多態主要有如下三種方式:
3.Java 中實現多態的機制是什麼?
內部類Lambda
1.內部類的做用?
- 內部類能夠有多個實例,每一個實例都有本身的狀態信息,而且與其餘外圍對象的信息相互獨立.在單個外圍類當中,可讓多個內部類以不一樣的方式實現同一接口,或者繼承同一個類.建立內部類對象的時刻不依賴於外部類對象的建立。
- 內部類提供了更好的封裝,除了該外圍類,其餘類都不能訪問。
2.一個java文件內部能夠有類?(非內部類)
- 只能有一個public公共類,可是能夠有多個default修飾的類。
3.Lambda的使用前提是什麼?
- 當須要一個接口的實現類對象,且接口中有且僅有一個抽象方法的時候,能夠使用lambda完成這個實現類要作的事情;(替代匿名內部類)
4.Lambda與匿名內部類區別
- lambda表達式編譯後並不會生成.class文件,而匿名內部類編譯後會產生單獨的class文件;
- 匿名內部類能夠用在類,抽象類,接口中,而lambda表達式只能用在有且僅有一個抽象方法的接口中;
static關鍵字
1.是否能夠在static環境中訪問非static變量?
- static變量在Java中是屬於類的,它在全部的實例中的值是同樣的。當類被Java虛擬機載入的時候,會對static變量進行初始化。若是你的代碼嘗試不用實例來訪問非static的變量,編譯器會報錯,由於這些變量尚未被建立出來,尚未跟任何實例關聯上。
2.static都有哪些用法?
- 被static所修飾的變量/方法都屬於類的靜態資源,類實例所共享.
- static也用於靜態塊,多用於初始化操做.
- 此外static也多用於修飾內部類,此時稱之爲靜態內部類.
3.靜態變量和實例變量的區別?
- 靜態變量存儲在方法區,屬於類全部。實例變量存儲在堆當中,其引用存在當前線程棧。
4.static特色
- 若是修飾構造代碼塊,僅在類第一次加載的時候,執行一次;
- 若是修飾成員變量,這個變量的值屬於類;能夠被全部的對象共享;
- 若是修飾成員方法,在方法中不能使用this,super;
- 靜態的內容優先於對象存在!
數據類型
1.String s1=」ab」, String s2=」a」+」b」, String s3=」a」, String s4=」b」, s5=s3+s4請問s5==s2返回什麼?
- 返回false。在編譯過程當中,編譯器會將s2直接優化爲」ab」,會將其放置在常量池當中,s5則是被建立在堆區,至關於s5=new String(「ab」);
2.3*0.1==0.3返回值是什麼
3.基本數據類型的默認值?基本數據類型所佔的字節以及封裝他們的類?
-
默認值
-
所佔字節
-
byte 1個字節--Byte
-
short 2個字節--Short
-
char 2個字節--Character
-
int 4個字節--Integer
-
long 8個字節--Long
-
float 4個字節--Float
-
double 8個字節--Double
4.String屬於那個類,以及經常使用的方法?
5.String, StringBuffer和StringBuilder區別
- String的值是不可改變的,這就致使每次對String的操做都會生成新的String對象,不由效率底下, 並且浪費大量的內存空間;
- StringBuilder是可變類,任何對他指向的字符串的操做都不會產生新的對 象,但單線程不安全;
- StringBuffer底層方法使用了synchronized關鍵字,線程比較安全,但效率 較StringBuilder慢
異常相關
1.error和exception有什麼區別
- error表示系統級的錯誤,是java運行環境內部錯誤或者硬件問題,不能期望程序來處理這樣的問題,除了退出運行外別無選擇,它是Java虛擬機拋出的。
- exception 表示程序須要捕捉、須要處理的異常,是由與程序設計的不完善而出現的問題,程序必須處理的問題
2.運行時異常和通常異常有何不一樣
- Java提供了兩類主要的異常:runtimeException和checkedException
- 通常異常(checkedException)主要是指IO異常、SQL異常等。對於這種異常,JVM要求咱們必須對其進行cathc處理,因此,面對這種異常,無論咱們是否願意,都是要寫一大堆的catch塊去處理可能出現的異常。
- 運行時異常(runtimeException)咱們通常不處理,當出現這類異常的時候程序會由虛擬機接管。好比,咱們歷來沒有去處理過NullPointerException,並且這個異常仍是最多見的異常之一。
- 出現運行時異常的時候,程序會將異常一直向上拋,一直拋到遇處處理代碼,若是沒有catch塊進行處理,到了最上層,若是是多線程就有Thread.run()拋出,若是不是多線程那麼就由main.run()拋出。拋出以後,若是是線程,那麼該線程也就終止了,若是是主程序,那麼該程序也就終止了。
- 其實運行時異常的也是繼承自Exception,也能夠用catch塊對其處理,只是咱們通常不處理罷了,也就是說,若是不對運行時異常進行catch處理,那麼結果不是線程退出就是主程序終止。
- 若是不想終止,那麼咱們就必須捕獲全部可能出現的運行時異常。若是程序中出現了異常數據,可是它不影響下面的程序執行,那麼咱們就該在catch塊裏面將異常數據捨棄,而後記錄日誌。若是,它影響到了下面的程序運行,那麼仍是程序退出比較好些。
3.Java中異常處理機制的原理
Java經過面向對象的方式對異常進行處理,Java把異常按照不一樣的類型進行分類,並提供了良好的接口。當一個方法出現異常後就會拋出一個異常對象,該對象中包含有異常信息,調用這個對象的方法能夠捕獲到這個異常並對異常進行處理。Java的異常處理是經過5個關鍵詞來實現的:try catch throw throws finally。
通常狀況下是用try來執行一段程序,若是出現異常,系統會拋出(throws),咱們能夠經過它的類型來捕捉它,或最後由缺省處理器來處理它(finally)。
- try:用來指定一塊預防全部異常的程序
- catch:緊跟在try後面,用來捕獲異常
- throw:用來明確的拋出一個異常
- throws:用來標明一個成員函數可能拋出的各類異常
- finally:確保一段代碼不管發生什麼異常都會被執行的一段代碼。
4.你平時在項目中是怎樣對異常進行處理的。
- 儘可能避免出現runtimeException 。例如對於可能出現空指針的代碼,帶使用對象以前必定要判斷一下該對象是否爲空,必要的時候對runtimeException
也進行try catch處理。
- 進行try catch處理的時候要在catch代碼塊中對異常信息進行記錄,經過調用異常類的相關方法獲取到異常的相關信息,返回到web端,不只要給用戶良好的用戶體驗,也要能幫助程序員良好的定位異常出現的位置及緣由。例如,之前作的一個項目,程序遇到異常頁面會顯示一個圖片告訴用戶哪些操做致使程序出現了什麼異常,同時圖片上有一個按鈕用來點擊展現異常的詳細信息給程序員看的。
5.throw和throws有什麼區別?
- throw關鍵字用來在程序中明確的拋出異常,相反,throws語句用來代表方法不能處理的異常。每個方法都必需要指定哪些異常不能處理,因此方法的調用者纔可以確保處理可能發生的異常,多個異常是用逗號分隔的。
6.異常處理的時候,finally代碼塊的重要性是什麼?
- 不管是否拋出異常,finally代碼塊老是會被執行。就算是沒有catch語句同時又拋出異常的狀況下,finally代碼塊仍然會被執行。最後要說的是,finally代碼塊主要用來釋放資源,好比:I/O緩衝區,數據庫鏈接。
7.請列出 5 個運行時異常?
- NullPointerException 空指針
- IndexOutOfBoundsException 索引越界
- ClassCastException 類型轉換異常
- ArrayStoreException 當你試圖將錯誤類型的對象存儲到一個對象數組時拋出的異常
- BufferOverflowException 寫入的長度超出了容許的長度
- IllegalArgumentException 方法的參數無效
- NoClassDefFoundException - JAVA運行時系統找不到所引用的類
8.try catch finally,try裏有return,finally還執行麼?**
- finally語句總會執行即便try裏包含continue,break,return,try塊結束後,finally塊也會執行
- 若是try、catch中有return語句,finally中沒有return,那麼在finally中修改除包裝類型和靜態變量、全局變量之外的數據都不會對try、catch中返回的變量有任何的影響(包裝類型、靜態變量會改變、全局變量)
- 儘可能不要在finally中使用return語句,若是使用的話,會忽略try、catch中的返回語句,也會忽略try、catch中的異常,屏蔽了錯誤的發生。
- finally中避免再次拋出異常,一旦finally中發生異常,代碼執行將會拋出finally中的異常信息,try、catch中的異常將被忽略
集合部分
一、List、Map、Set三個接口,存取元素時,各有什麼特色?
- Set集合的add有一個boolean類型的返回值,當集合中沒有某個元素時,則能夠成功加入該 元素,返回結果爲true;當集合中存在與某個元素equals方法相等 的元素時,則沒法加入該元素, 取元素時只能用Iterator接口取得全部元素,在逐一遍歷各個元素;
- List表示有前後順序的集合,調用add()方法,指定當前對象在集合中的存放位置;一個對象可 以被反覆存進集合中;每調用一次add()方法,該對象就會被插入集合中一次,其實,並非把對 象自己存進了集合中,而是在集合中使用一個索引變量指向了該對象,當一個對象被add屢次時, 即有多個索引指向了這個對象。List去元素時能夠使用Iterator取出全部元素,在逐一遍歷,還可 以使用get(int index)獲取指定下表的元素;
- Map是雙列元素的集合,調用put(key,value),要存儲一對key/value,不能存儲重複的key, 這個是根據eauals來判斷;取元素時用get(key)來獲取key所對 應的value,另外還能夠獲取 所有key,所有value
二、ArrayList和LinkedList的底層實現原理?他們爲何線程不安全?在多線程併發操做下,咱們應該用什麼替代?
- ArrayList底層經過數組實現,ArrayList容許按序號索引元素,而插入元素須要對數組進行移位等內存操做,因此索引快插入較慢;(擴容方式)一旦咱們實例化了ArrayList 無參構造函數默認數組長度爲10。add方法底層如 果增長的元素超過了10個,那麼ArrayList底層會生成一個新的數組,長度爲原來數組長度的1.5倍+1,而後將原數組內容複製到新數組中,而且後續加的內容都會放到新數組中。當新數組沒法容納增長元素時,重複該過程;
- LinkedList底層經過雙向鏈表實現,取元素時須要進行前項或後項的遍歷,插入元素時只須要記錄本項的先後 項便可,因此插入快查詢慢;
- ArrayList和LinkedList底層方法都沒有加synchronized關鍵詞,多線程訪問時會出現多個線程前後更改數據形成獲得的數據是髒數據;多線程併發操做下使用Vector來代替,Vector底層也是數組,但底層方法都加synchronized關鍵字使線程安全,效率較ArrayList差;
三、HashMap和HashTable有什麼區別?其底層實現是什麼?CurrentHashMap的鎖機制又是如何?若是想將一個Map變爲有序的,該如何實現?
- 區別:
- HashMap沒有實現synchronized線程非安全,HashTable實現了synchronized線程安全;
- HashMap容許key和value爲null,而HashTable不容許
- 底層原理:數組+鏈表實現
- ConcurrentHashMap鎖分段技術:HashTable效率低下的緣由,是由於所訪問HashTable的線程都必須競爭同一把鎖,那假如容器中有多把鎖,每一把鎖用於鎖住容器中的一部分數據,那麼當多線程訪問容器中不一樣的數據時,線程間就不會存在鎖競爭,從而提升併發訪問率;ConcurrentHashMap使用的就是鎖分段技術,首先將數據分紅一段一段的存儲,而後給每一段數據配一把鎖,當一個線程佔用鎖訪問其中一個數據時,其餘段的數據也能被其餘線程訪問;
- 實現TreeMap
4.什麼是迭代器(Iterator)?
- Iterator接口提供了不少對集合元素進行迭代的方法。每個集合類都包含了能夠返回迭代器實例的迭代方法。迭代器能夠在迭代的過程當中刪除底層集合的元素,可是不能夠直接調用集合的remove(Object Obj)刪除,能夠經過迭代器的remove()方法刪除
5.Arraylist 與 LinkedList 區別
- Arraylist:
- 優勢:ArrayList是實現了基於動態數組的數據結構,由於地址連續,一旦數據存儲好了,查詢操做效率會比較高(在內存裏是連着放的)。
- 缺點:由於地址連續, ArrayList要移動數據,因此插入和刪除操做效率比較低。
- LinkedList:
- 優勢:LinkedList基於鏈表的數據結構,地址是任意的,因此在開闢內存空間的時候不須要等一個連續的地址,對於新增和刪除操做add和remove,LinedList比較佔優點。LinkedList 適用於要頭尾操做或插入指定位置的場景
- 缺點:由於LinkedList要移動指針,因此查詢操做性能比較低。
6.Arraylist 與 LinkedList 應用場景?
- 當須要對數據進行對此訪問的狀況下選用ArrayList,當須要對數據進行屢次增長刪除修改時採用LinkedList。
7.Collection 和 Collections的區別
- Collection是集合類的上級接口,繼承與他的接口主要有Set 和List.Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各類集合的搜索、排序、線程安全化等操做(帶s的基本都是工具類,如Arrays)
8.爲什麼Map接口不繼承Collection接口?
- 儘管Map接口和它的實現也是集合框架的一部分,但Map不是集合,集合也不是Map。所以,Map繼承Collection毫無心義,反之亦然。
- 若是Map繼承Collection接口,那麼元素去哪兒?Map包含key-value對,它提供抽取key或value列表集合的方法,可是它不適合「一組對象」規範。
10.HashMap和Hashtable有什麼區別?
- HashMap是非線程安全的,HashTable是線程安全的。
- HashMap的鍵和值都容許有null值存在,而HashTable則不行。
- 由於線程安全的問題,HashMap效率比HashTable的要高。
- Hashtable是同步的,而HashMap不是。所以,HashMap更適合於單線程環境,而Hashtable適合於多線程環境。
通常如今不建議用HashTable
- 是HashTable是遺留類,內部實現不少沒優化和冗餘
- 即便在多線程環境下,如今也有同步的ConcurrentHashMap替代,沒有必要由於是多線程而用HashTable。
11.List 和 Set 區別?
List,Set都是繼承自Collection接口
(注意:元素雖然無放入順序,可是元素在set中的位置是有該元素的HashCode決定的,其位置實際上是固定的,加入Set 的Object必須定義equals()方法 ,另外list支持for循環,也就是經過下標來遍歷,也能夠用迭代器,可是set只能用迭代,由於他無序,沒法用下標來取得想要的值。)
12.Set和List對比?
- Set:檢索元素效率低下,刪除和插入效率高,插入和刪除不會引發元素位置改變。
- List:和數組相似,List能夠動態增加,查找元素效率高,插入刪除元素效率低,由於會引發其餘元素位置改變。
13.當兩個對象的hashcode相同會發生什麼?
- 由於hashcde相同,因此它們的bucket位置相同,‘碰撞’會發生。由於HashMap使用鏈表存儲對象,這個Entry(包含有鍵值對的Map.Entry對象)會存儲在鏈表中。
14.若是兩個鍵的hashcode相同,你如何獲取值對象?
- 當咱們調用get()方法,HashMap會使用鍵對象的hashcode找到bucket位置,而後會調用keys.equals()方法去找到鏈表中正確的節點,最終找到要找的值對象。
15.有沒有可能兩個不相等的對象有相同的hashcode?
- 有可能,(通話,重地)兩個不相等的對象可能會有相同的 hashcode 值,這就是爲何在 hashmap 中會有衝突。若是兩個對象相等,必須有相同的hashcode 值,反之不成立。
16.HashMap、LinkedHashMap、TreeMap的區別?
- HashMap是根據鍵的hashcode值存儲數據,根據鍵能夠直接獲取它的值,具備很快的訪問速度,取得的數據徹底是隨機的
- LinkedHashMap保存了記錄的插入順序,在使用Iterator進行遍歷的時候,先獲得的確定是先插入的數據,能夠在構造時帶參數,按照應用次數來進行排序
- TreeMap實現SortMap接口,可以把它保存的記錄根據鍵排序。默認的是升序排序,也能夠指定排序的比較器,進行遍歷的時候獲得的是排序過的記錄。
17.HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底層實現。**
- HashMap是java數據結構中兩大結構數組和鏈表的組合。HashMap底層數組,數組中的每一項又是一個鏈表。程序會先根據key的hashcode()方法返回值決定該Entry在數組中的
- 存儲位置,若是該位置上沒有元素,就會將元素放置在此位置上,若是兩個Entry的key相同,會調用equals,返回值是true則覆蓋原來的value值,返回false則會造成Entry鏈,位於頭部。
- ArrrayList的底層實現是數組,在執行add操做時,會先檢查數組 大小是否能夠容納新的元素,若是不夠就會進行擴容。而後會將原來的數據拷貝到新的數組中。
- LinkedList底層是一個鏈表,其實現增刪改查和數據結構中的操做徹底相同,並且插入是有序的。
- LinkedHashMap的底層結構式是雙鏈表,其餘的邏輯處理與HashMap一致,一樣沒有鎖保護,多線程使用時存在風險。
- ConcurrentHashMap是segment數組結構和HashEntry數組結構組成的,segment在ConcurrentHashMap中充當鎖的角色,HashEntry用於存儲鍵值對數據。segment的結構是數組和鏈表,一個segment中有一個HashEntry,每一個HashEntry是一個鏈表結構的元素。對HashEntry中的數據進行修改時,須要先得到它所對應的segment鎖。每一個ConcurrentHashMap默認有16個segment。
18.==和 equals hashCode 的區別?
- 基本數據類型: ==比較的是內容 引用數據類型: ==比的是地址值,equals默認比地址值,重寫按照規則比較,hashCode
19.天然排序Comparble和比較器排序Comparator的異同點?
相同點:
返回值的規則:
-
若是返回值爲負數,表示當前存入的元素是較小值,存左邊
-
若是返回值爲0,表示當前存入的元素跟集合中元素重複了,不存
-
若是返回值爲正數,表示當前存入的元素是較大值,存右邊
不一樣點:
1.用到的接口不一樣
-
天然排序: 自定義類實現Comparable接口,重寫compareTo方法,根據返回值進行排序
-
比較器排序: 建立TreeSet對象的時候傳遞Comparator的實現類對象,重寫compare方法,根據返回值進行排序
2.使用場景不一樣
-
天然排序能知足大部分狀況
-
存儲沒有修改權限的類時能夠使用
20.Iterator 和 ListIterator 有什麼區別?
-
Iterator可用來遍歷Set和List集合,可是ListIterator只能用來遍歷List。
-
Iterator對集合只能是前向遍歷,ListIterator既能夠前向也能夠後向。
-
ListIterator實現了Iterator接口,幷包含其餘的功能,好比:增長元素,替換元素,獲取前一個和後一個元素的索引,等等。
泛型
1.爲何使用泛型?
- 它提供了編譯時類型安全檢測機制,把運行時期的問題提早到了編譯期間
- 避免了強制類型轉換
2.泛型用在什麼地方?
3.如何使用泛型類?
- 建立泛型類對象時,必需要給這個泛型肯定具體的數據類型
樹
1.什麼是二叉樹?
2.什麼是二叉查找樹?
- 每一個節點最多有兩個子節點,左邊比當前節點小,右邊比當前節點大
3.什麼是平衡二叉樹?
- 二叉樹左右子樹的樹高差不超過1,任意節點的左右子樹都是平衡二叉樹
- 經過左旋右旋保持樹的平衡
序列化
1.什麼是 Java 序列化?
- 序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。
- 能夠對流化後的對象進行讀寫操做,也可將流化後的對象傳輸於網絡之間。
- 序列化是爲了解決在對對象流進行讀寫操做時所引起的問題。
- 反序列化的過程,則是和序列化相反的過程。
- 另外,咱們不能將序列化侷限在 Java 對象轉換成二進制數組,例如說,咱們將一個 Java 對象,轉換成 JSON 字符串,或者 XML 字符串,這也能夠理解爲是序列化。
2.如何實現 Java 序列化?
將須要被序列化的類,實現 Serializable 接口,該接口沒有須要實現的方法,implements Serializable 只是爲了標註該對象是可被序列化的。
序列化
- 而後,使用一個輸出流(如:FileOutputStream)來構造一個 ObjectOutputStream(對象流)對象,接着,使用 ObjectOutputStream 對象的 #writeObject(Object obj) 方法,就能夠將參數爲 obj 的對象寫出(即保存其狀態)。
反序列化
3.Java 序列話中,若是有些字段不想進行序列化怎麼辦?
- 對於不想進行序列化的變量,使用 transient 關鍵字修飾。
- 當對象被序列化時,阻止實例中那些用此關鍵字修飾的的變量序列化。
- 當對象被反序列化時,被 transient 修飾的變量值不會被持久化和恢復。
- transient 只能修飾變量,不能修飾類和方法。
4.對象操做流是字符流仍是字節流?
5.如何在讀寫文件時指定字符集?
jdk11以前:
- 使用轉換流InputStreamReader(輸入轉換流)字節轉換字符橋樑/OutputStreamWriter(輸出轉換流)字符轉字節橋樑
jdk11以後
6.字符緩衝流特有方法?
- readLine():讀取一整行,到達尾處爲null
- newLine():跨平臺換行
7.爲何使用對象流?
- 在開發中,常常須要將對象的信息保存到磁盤中,若是使用前面所學的知識來實現,會很是的繁瑣。使用對象流就很是的方便
- 對象操做流能夠將對象以字節的形式寫到本地文件中,直接打開是看不懂的,須要時能夠再次用對象操做流讀到內存中
多線程
1.什麼是線程?
- 線程是操做系統可以進行運算調度的最小單位,它被包含在進程之中,是進程中的實際運做單位。線程是進程的一部分,是進程中的單個控制流,是一條執行路徑
2.線程和進程有什麼區別?
- 線程是進程的子集,一個進程能夠有不少線程,每條線程並行執行不一樣的任務。不一樣的進程使用不一樣的內存空間,而全部的線程共享一片相同的內存空間。
3.如何在Java中實現線程?
- 繼承Thread:
- 實現Runnable接口:
- 實現Runnable接口,將實現類做爲參數傳遞給Thread對象
- 實現Callable接口:
- 實現Callabale接口,建立FutureTask對象,將Callable做爲參數傳遞給FutureTask對象,再將FutureTask對象傳遞給Thread類
4.用Runnable仍是Thread?
Java不支持類的多重繼承,但容許你調用多個接口。因此若是你要繼承其餘類,固然是調用Runnable接口好了。
- Thread:
- Runnable,Callable:
- 擴展性比較強,優先使用Runnable接口,須要執行完有返回值能夠選擇Callable接口
5.Thread 類中的start() 和 run() 方法有什麼區別?
- start()方法被用來啓動新建立的線程,並且start()內部調用了run()方法,這和直接調用run()方法的效果不同。
當你調用run()方法的時候,只會是在原來的線程中調用,沒有新的線程啓動,start()方法纔會啓動新線程。
6.Java中Runnable和Callable有什麼不一樣?
- Runnable和Callable都表明那些要在不一樣的線程中執行的任務。Runnable從JDK1.0開始就有了,Callable是在JDK1.5增長的。它們的主要區別是Callable的 call() 方法能夠返回值和拋出異常,而Runnable的run()方法沒有這些功能。Callable能夠返回裝載有計算結果的Future對象。
7.Java內存模型是什麼?
Java內存模型規定和指引Java程序在不一樣的內存架構、CPU和操做系統間有肯定性地行爲。它在多線程的狀況下尤爲重要。Java內存模型對一個線程所作的變更能被其它線程可見提供了保證,它們之間是先行發生關係。這個關係定義了一些規則讓程序員在併發編程時思路更清晰。好比,先行發生關係確保了:
-
線程內的代碼可以按前後順序執行,這被稱爲程序次序規則。
-
對於同一個鎖,一個解鎖操做必定要發生在時間上後發生的另外一個鎖定操做以前,也叫作管程鎖定規則。
-
前一個對volatile的寫操做在後一個volatile的讀操做以前,也叫volatile變量規則。
-
一個線程內的任何操做必需在這個線程的start()調用以後,也叫做線程啓動規則。
-
一個線程的全部操做都會在線程終止以前,線程終止規則。
-
一個對象的終結操做必需在這個對象構造完成以後,也叫對象終結規則。
-
可傳遞性
8.Java中的volatile 變量是什麼?
- volatile是一個特殊的修飾符,只有成員變量才能使用它。在Java併發程序缺乏同步類的狀況下,多線程對成員變量的操做對其它線程是透明的。volatile變量能夠保證下一個讀取操做會在前一個寫操做以後發生,就是上一題的volatile變量規則。
9.什麼是線程安全?Vector是一個線程安全類嗎?
- 多個線程可能會同時運行同一段代碼。若是每次運行結果和單線程運行的結果是同樣的,並且其餘的變量的值也和預期的是同樣的,就是線程安全的。一個線程安全的計數器類的同一個實例對象在被多個線程使用的狀況下也不會出現計算失誤。很顯然你能夠將集合類分紅兩組,線程安全和非線程安全的。Vector 是用同步方法來實現線程安全的, 而和它類似的ArrayList不是線程安全的。
10.Java中如何中止一個線程?
- 當run() 或者 call() 方法執行完的時候線程會自動結束,若是要手動結束一個線程,你能夠用volatile 布爾變量或設置某個變量達到必定值的時候,來退出run()方法的循環或者是取消任務來中斷線程。
11.Java中notify 和 notifyAll有什麼區別?
- notify()方法不能喚醒某個具體的線程,因此只有一個線程在等待的時候它纔有用武之地。
- notifyAll()喚醒全部線程並容許他們爭奪鎖確保了至少有一個線程能繼續運行
12. 什麼是線程池? 爲何要使用它?
- 建立線程要花費昂貴的資源和時間,若是任務來了才建立線程那麼響應時間會變長,並且一個進程能建立的線程數有限。爲了不這些問題,在程序啓動的時候就建立若干線程來響應處理,它們被稱爲線程池,裏面的線程叫工做線程。從JDK1.5開始,Java API提供了Executor框架讓你能夠建立不一樣的線程池。好比單線程池,每次處理一個任務;數目固定的線程池或者是緩存線程池(一個適合不少生存期短的任務的程序的可擴展線程池)
13.如何寫代碼來解決生產者消費者問題?
- 在現實中你解決的許多線程問題都屬於生產者消費者模型,就是一個線程生產任務供其它線程進行消費,你必須知道怎麼進行線程間通訊來解決這個問題。比較低級的辦法是用wait和notify來解決這個問題,比較讚的辦法是用Semaphore 或者 BlockingQueue來實現生產者消費者模型
14.Java多線程中的死鎖
死鎖是指兩個或兩個以上的進程在執行過程當中,因爭奪資源而形成的一種互相等待的現象,若無外力做用,它們都將沒法推動下去。這是一個嚴重的問題,由於死鎖會讓你的程序掛起沒法完成任務,死鎖的發生必須知足如下四個條件:
-
互斥條件:一個資源每次只能被一個進程使用。
-
請求與保持條件:一個進程因請求資源而阻塞時,對已得到的資源保持不放。
-
不剝奪條件:進程已得到的資源,在末使用完以前,不能強行剝奪。
-
循環等待條件:若干進程之間造成一種頭尾相接的循環等待資源關係。
避免死鎖最簡單的方法就是阻止循環等待條件,將系統中全部的資源設置標誌位、排序,規定全部的進程申請資源必須以必定的順序(升序或降序)作操做來避免死鎖。
15.Java中synchronized 和 ReentrantLock 有什麼不一樣?
- 這兩種方式最大區別就是對於Synchronized來講,它是java語言的關鍵字,是原生語法層面的互斥,須要jvm實現。而ReentrantLock它是JDK 1.5以後提供的API層面的互斥鎖,須要lock()和unlock()方法配合try/finally語句塊來完成。
16.詳談Synchronized
當Synchronized關鍵字修飾一個方法的時候,該方法叫作同步方法:java中的每一個對象都有一個鎖(lock)或者叫作監視器(monitor),當訪問某個對象的synchronized方法的時候,表示將對象上鎖,此時其它任何線程都沒法再去訪問synchronized方法了,直到以前的那個線程執行方法完畢後(或者是拋出了異常),那麼將該對象的鎖釋放掉,其餘線程纔有可能再去訪問該synchronized方法。
- 注意1:
- 若是一個對象有多個synchronized方法,某一個時刻某個線程已經進入到了某個synchronized方法,那麼在該方法沒有執行完畢前,其它線程是沒法訪問該對象的任何synchronzed方法的。
- 注意2:
- 若是某個Synchronized方法是static的,那麼當線程訪問該方法時,它鎖的並非Synchronized方法所在的對象,而是Synchronized方法所在的對象所對象的Class對象,由於java中不管一個類有多少個對象,這些對象會對應惟一一個class對象,所以當線程分別訪問同一個類的兩個對象的兩個static Synchronized方法的時候,他們執行的順序也是順序的,也就是說一個線程先去執行方法,執行完畢後另外一個線程纔開始執行。
- 注意3:
- jdk1.6以後對synchronized(偏向鎖(根本就不加鎖)、輕量級鎖(CAS),重量級鎖(悲觀鎖))進行了大量的優化
17.在Java中Lock接口與synchronized塊的區別是什麼?
- 用法不同。synchronized既能夠加在方法上,也能夠加載特定的代碼塊上,括號中表示須要鎖的對象。而Lock須要顯示地指定起始位置和終止位置。synchronzied是託管給jvm執行的,Lock鎖定是經過代碼實現的。
- 在性能上來講,若是競爭資源不激烈,二者的性能是差很少的,而當競爭資源很是激烈時(即有大量線程同時競爭),此時Lock的性能要遠遠優於synchronized。因此說,在具體使用時要根據適當狀況選擇。
- 鎖的機制不同。synchronized得到鎖和釋放的方式都是在塊結構中,並且是自動釋放鎖。而Lock則須要開發人員手動去釋放,而且必須在finally塊中釋放,不然會引發死鎖問題的發生。
- Lock是一個接口,而synchronized是Java中的關鍵字,synchronized是內置的語言實現;
- synchronized在發生異常時,會自動釋放線程佔有的鎖,所以不會致使死鎖現象發生;而Lock在發生異常時,若是沒有主動經過unLock()去釋放鎖,則極可能形成死鎖現象,所以使用Lock時須要在finally塊中釋放鎖
18.synchronized 的原理是什麼?有什麼不足?
- 原理:
- synchronized是 Java 內置的關鍵字,它提供了一種獨佔的加鎖方式。
- synchronized的獲取和釋放鎖由JVM實現,用戶不須要顯示的釋放鎖,很是方便。
- 不足:
- 當線程嘗試獲取鎖的時候,若是獲取不到鎖會一直阻塞。
- 若是獲取鎖的線程進入休眠或者阻塞,除非當前線程異常,不然其餘線程嘗試獲取鎖必須一直等待。
19.關於成員變量和局部變量
- 若是一個變量是成員變量,那麼多個線程對同一個對象的成員變量進行操做的時候,他們對該成員變量是彼此影響的,也就是說一個線程對成員變量的改變會影響到另一個線程;若是一個變量是局部變量,那麼每一個線程都會有一個該局部變量的拷貝,一個線程對該局部變量的改變不會影響到其它的線程。
20. 若是你提交任務時,線程池隊列已滿。會時發會生什麼?
- 若是一個任務不能被調度執行那麼ThreadPoolExecutor’s submit()方法將會拋出一個RejectedExecutionException異常。
21.volatile關鍵字的做用是?
- 保證變量的可見性。
- 在java內存結構中,每一個線程都是有本身獨立的內存空間(此處指的線程棧)。當須要對一個共享變量操做時,線程會將這個數據從主存空間複製到本身的獨立空間內進行操做,而後在某個時刻將修改後的值刷新到主存空間。這個中間時間就會發生許多奇奇怪怪的線程安全問題了,volatile就出來了,它保證讀取數據時只從主存空間讀取,修改數據直接修改到主存空間中去,這樣就保證了這個變量對多個操做線程的可見性了。換句話說,被volatile修飾的變量,能保證該變量的 單次讀或者單次寫 操做是原子的。
- 可是線程安全是兩方面須要的 原子性(指的是多條操做)和可見性。volatile只能保證可見性,synchronized是兩個均保證的。
- volatile輕量級,只能修飾變量;synchronized重量級,還可修飾方法。
- volatile不會形成線程的阻塞,而synchronized可能會形成線程的阻塞。
22.守護線程和非守護線程有什麼區別?
- 程序運行完畢,JVM 會等待非守護線程完成後關閉,可是 JVM 不會等待守護線程
23.線程的生命週期?
線程的生命週期包含5個階段,包括:新建、就緒、運行、阻塞、銷燬。
-
新建:就是剛使用new方法,new出來的線程;
-
就緒:就是調用的線程的start()方法後,這時候線程處於等待CPU分配資源階段,誰先搶的CPU資源,誰開始執行;
-
運行:當就緒的線程被調度並得到CPU資源時,便進入運行狀態,run方法定義了線程的操做和功能;
-
阻塞:在運行狀態的時候,可能由於某些緣由致使運行狀態的線程變成了阻塞狀態,好比sleep()、wait()以後線程就處於了阻塞狀態,這個時候須要其餘機制將處於阻塞狀態的線程喚醒,好比調用notify或者notifyAll()方法。喚醒的線程不會馬上執行run方法,它們要再次等待CPU分配資源進入運行狀態;
-
銷燬:若是線程正常執行完畢後或線程被提早強制性的終止或出現異常致使結束,那麼線程就要被銷燬,釋放資源;
24.wait和sleep,notify()鎖方面區別?
- wait:讓線程等待,同時當即釋放鎖
- sleep():讓線程休眠,可是不會釋放鎖
- notify()或notifyAll(): 喚醒等待的線程,可是不會當即釋放鎖
25.什麼狀況下會出現線程安全問題?
26.Java中規定了線程有哪幾種狀態?
27.什麼是原子性?
- 所謂的原子性就是完成功能的全部操做要麼都執行,要麼都不執行
28.Java中哪些操做是原子操做?
- 除了long和double以外的全部原始類型的賦值
- 全部volatile變量的賦值
- java.concurrent.Atomic *類的全部操做
29.什麼是CAS算法?
- 當預期值E==主內存中的值V,此時能夠進行修改,將V改爲新值
- 當預期值E!=主內存中的值V時,將主內存中的已經改變的值更新到本身的工做內存中,再次嘗試比較,直到預期值E等於主內存中的值V,才能夠修改。這個過程稱爲自旋
30.synchronized和CAS的區別?
- 相同點:
- 不一樣點:
- synchronized老是從最壞的角度出發,認爲每次獲取數據的時候,別人都有可能修改。因此在每 次操做共享數據以前,都會上鎖。(悲觀鎖)
- CAS是從樂觀的角度出發,假設每次獲取數據別人都不會修改,因此不會上鎖。只不過在修改共享數據的時候,會檢查一下,別人有沒有修改過這個數據。若是別人修改過,那麼我再次獲取如今最新的值。若是別人沒有修改過,那麼我如今直接修改共享數據的值.(樂觀鎖)
31.併發容器Hashtable和ConcurrentHashMap特色?
- Hashtable:
- ConcurrentHashMap:
反射類加載器
1.Java反射機制的做用?
- 在運行時判斷任意一個對象所屬的類。
- 在運行時判斷任意一個類所具備的成員變量和方法。
- 在運行時任意調用一個對象的方法
- 在運行時構造任意一個類的對象
2.什麼是反射機制?
- 簡單說,反射機制值得是程序在運行時可以獲取自身的信息。在java中,只要給定類的名字,那麼就能夠經過反射機制來得到類的全部信息。
3.哪裏用到反射機制?
- Spring 框架的 IoC 基於反射建立對象和設置依賴屬性。
- Spring MVC 的請求調用對應方法,也是經過反射。
- JDBC 的 Class#forName(String className) 方法,也是使用反射。
4.反射機制的優缺點?
- 靜態編譯:
- 動態編譯:
- 運行時肯定類型,綁定對象。動態編譯最大限度的發揮了java的靈活性,體現了多態的應用,有利於下降類之間的耦合性。一句話,反射機制的優勢就是能夠實現動態建立對象和編譯,體現出很大的靈活性,特別是在J2EE的開發中它的靈活性就表現的十分明顯。好比,一個大型的軟件,不可能一次就把把它設計的很完美,當這個程序編譯後,發佈了,當發現須要更新某些功能時,咱們不可能要用戶把之前的卸載,再從新安裝新的版本,假如這樣的話,這個軟件確定是沒有多少人用的。採用靜態的話,須要把整個程序從新編譯一次才能夠實現功能的更新,而採用反射機制的話,它就能夠不用卸載,只須要在運行時才動態的建立和編譯,就能夠實現該功能。它的缺點是對性能有影響。使用反射基本上是一種解釋操做,咱們能夠告訴JVM,咱們但願作什麼而且它知足咱們的要求。這類操做老是慢於只直接執行相同的操做
5.反射中,Class.forName 和 ClassLoader 區別
- java中class.forName()和classLoader均可用來對類進行加載。
- class.forName()前者除了將類的.class文件加載到jvm中以外,還會對類進行解釋,執行類中的static塊。
- 而classLoader只幹一件事情,就是將.class文件加載到jvm中,不會執行static中的內容,只有在newInstance纔會去執行static塊。
6.什麼是雙親委派模型?
- 若是一個類加載器收到了類加載請求,它並不會本身先去加載,而是把這個請求委託給父類的加載器去執行,若是父類加載器還存在其父類加載器,則進一步向上委託,依次遞歸,請求最終將到達頂層的啓動類加載器,若是父類加載器能夠完成類加載任務,就成功返回,假若父類加載器沒法完成此加載任務,子加載器纔會嘗試本身去加載,這就是雙親委派模式
7.爲何要有雙親委派模型?
- 爲了保證類的全局惟一性,若是自定義類與Java核心類庫中的類重名了,會被編譯但不會不執行
8.怎麼利用反射使用私有成員?
- setAccessible(boolean flag)
網絡通訊
1.什麼是三次握手?
-
客戶端向服務器發出取消鏈接請求
-
服務器向客戶端返回一個響應,告訴客戶端收到了請求
-
客戶端向服務器端再次發出確認信息創建鏈接
2.什麼是四次揮手?
3.TCP通訊注意事項?
-
accept方法是阻塞的,做用就是等待客戶端鏈接
-
客戶端建立對象並鏈接服務器,此時是經過三次握手協議,保證跟服務器之間的鏈接
-
針對客戶端來說,是往外寫的,因此是輸出流 針對服務器來說,是往裏讀的,因此是輸入流
-
read方法也是阻塞的
-
客戶端在關流的時候,還多了一個往服務器寫結束標記的動做
-
最後一步斷開鏈接,經過四次揮手協議保證鏈接終止
web階段
jsp相關
1.jsp內置對象和EL內置對象的區別與聯繫
jsp內置對象:
EL表達式內置對象:
pageContext對象是兩者惟一相同的對象,其餘都是各自獨立的對象
2.說一下 jsp 的 4 種做用域?
JSP中的四種做用域包括page、request、session和application,具體來講:
-
page表明與一個頁面相關的對象和屬性。
-
request表明與Web客戶機發出的一個請求相關的對象和屬性。一個請求可能跨越多個頁面,涉及多個Web組件;須要在頁面顯示的臨時數據能夠置於此做用域。
-
session表明與某個用戶與服務器創建的一次會話相關的對象和屬性。跟某個用戶相關的數據應該放在用戶本身的session中。
-
application表明與整個Web應用程序相關的對象和屬性,它實質上是跨越整個Web應用程序,包括多個頁面、請求和會話的一個全局做用域。
3.ServletContext 與application的異同
- 相同:
- 其實servletContext和application 是同樣的,就至關於一個類建立了兩個不一樣名稱的變量。在 servlet中ServletContext就是application對象。你們只要打開jsp編譯事後生成的Servlet中 jspService()方法就能夠看到以下的聲明: ServletContextapplication = null;application= pageContext.getServletContext();
- 不一樣:
- 二者的區別就是application用在jsp中,servletContext用在servlet中。application和page requestsession 都是JSP中的內置對象,在後臺用ServletContext存儲的屬性數據能夠用 application對象得到。 並且application的做用域是整個Tomcat啓動的過程。 例如:ServletContext.setAttribute("username",username); 則在JSP網頁中能夠使用 application.getAttribute("username"); 來獲得這個用戶名。
4.jsp 有哪些內置對象?做用分別是什麼?
JSP有9個內置對象:
-
request:封裝客戶端的請求,其中包含來自GET或POST請求的參數;
-
response:封裝服務器對客戶端的響應;
-
pageContext:經過該對象能夠獲取其餘對象;
-
session:封裝用戶會話的對象;
-
application:封裝服務器運行環境的對象;
-
out:輸出服務器響應的輸出流對象;
-
config:Web應用的配置對象;
-
page:JSP頁面自己(至關於Java程序中的this);
-
exception:封裝頁面拋出異常的對象。
概念相關
1.post和get區別?
-
-
get:
-
數據顯示在地址欄
-
不安全
-
get方式提交有大小限制(約4kb)
2.相對路徑和絕對路徑?
-
相對路徑
概念:
寫法:
-
絕對路徑
概念:
寫法:
3.Cookie和session的區別?
session是基於cookie
屢次請求之間共享數據
- cookie:
-
數據存儲於客戶端--不安全
-
只能存字符串
-
大小有限制
- session:
-
數據存儲於服務器端--安全
-
類型無限制
-
大小無限制
4.servlet四大域對象的區別?
5.什麼是活化與鈍化?
服務器自動完成(注意使用本地Tomcat才行)
- 鈍化:
- 活化:
-
概念:相反的狀態,從磁盤讀取到內存
-
時機:tomcat從新啓動時會將會話加載到內存
6.EL內置對象有哪些?
注意:EL 表達式內置對象和,JSP 內置對象不是一回事,el表達式中想要使用jsp 中的對象須要使用pageContext 獲取
7.若是有大量的網站訪問量。那麼會產生不少的session,該怎麼解決?
session默認保存在內存中,內存資源寶貴,session數據量大致使內存利用率高,如下方案解決session內存存儲問題:
- 能夠設置session超時時間,達到超時時間session自動清空
<session-config>
<session-timeout>20</session-timeout>
</session-config>
- 將session中的數據序列化到硬盤中
- 不使用session,使用cookie(此方法存在安全性問題)
8.頁面傳遞對象的方法?
- Request、session、application、cookie等
9.session 和 application的區別?
- 二者的做用範圍不一樣:
- Session對象是用戶級的,而Application是應用程序級別的
- 一個用戶一個session對象,每一個用戶的session對象不一樣,在用戶所訪問的網站多個頁面之間共享同一個session對象
- 一個Web應用程序一個application對象,每一個Web應用程序的application對象不一樣,但一個Web應用程序的多個用戶之間共享同一個application對象。
- 二者的生命週期不一樣:
- session對象的生命週期:用戶首次訪問網站建立,用戶離開該網站 (不必定要關閉瀏覽器) 消亡。
- application對象的生命週期:啓動Web服務器建立,關閉Web服務器銷燬。
Servlet相關
1.解釋一下什麼是servlet
- Servlet有良好的生存期的定義,包括加載和實例化、初始化、處理請求以及服務結束。這個生存期由javax.servlet.Servlet 接口的init,service 和destroy方法表達。
- Web容器加載Servlet,Servlet被服務器實例化後,生命週期開始。經過調用servlet的init()方法進行servlet的初始化。經過調用service()方法實現,根據請求的不一樣調用不一樣的doXXX方法(doGet,doPost)方法。結束服務,web容器調用servlet的destroy()方法。
2.servlet的生命週期?
servlet容器負責管理servlet的生命週期,servlet生命週期以下:
- 加載和實例化 Servlet 容器裝載和實例化一個 Servlet。建立出該 Servlet 類的一個實例。
- 初始化 在 Servlet 實例化完成以後,容器負責調用該 Servlet 實例的 init() 方法,在處理用戶請求以前,來作一些額外的初始化工做。
- 處理請求 當 Servlet 容器接收到一個 Servlet 請求時,便運行與之對應的 Servlet 實例的 service() 方法,service() 方法再派遣運行與請求相對應的 doXX(doGet,doPost) 方法來處理用戶請求。
- 銷燬 當 Servlet 容器決定將一個 Servlet 從服務器中移除時 ( 如 Servlet 文件被更新 ),便調用該 Servlet 實例的 destroy() 方法,在銷燬該 Servlet 實例以前, 來作一些其餘的工做。
加載實例化,初始化,銷燬,在整個生命週期中只會執行一次
補充:
3.servlet生命週期方法有哪些?
共有3個方法:
- public void init(ServletConfig config):
- 這個方法是由servlet容器調用用來初始化servlet的,這個方法在servlet生命週期中僅被調用一次。
- public void service(ServletRequest request, ServletResponse response):
- servlet容器爲每一個客戶端建立線程,而後都會執行service方法,但執行此方法前init方法必須已經被執行了。
- public void destroy():
- servlet從servlet容器中被移除時會調用此方法,僅被調用一次。
4.servlet過濾器的做用?
- 打印一些請求參數到日誌中
- 受權請求訪問資源
- 在將請求提交給servlet以前,對request請求頭或請求體進行一些格式化的處理
- 將響應數據進行壓縮再返回給瀏覽器。
- 解決亂碼問題。
5.servlet監聽器的做用?
- 監聽客戶端的請求,服務器端的操做等 。經過監聽器,能夠自動激發一些操做,好比監聽在線的用戶數量( 當增長一個HttpSession時,就自動觸發sessionCreated(HttpSessionEvent se)方法,在這個方法中就能夠統計在線人數了 ),另外還能夠用來初始化一些資源,好比數據庫鏈接池等(web.xml中配置的context-param只能是字符串不能使對象,這時就得使用ServletContextListener了,注意,有讀者可能說ServletConext的setAttribute不是能夠設置對象嗎?可是這是在servlet建立以後才能調用的方法,若是但願web應用一啓動就產生初始參數必須使用監聽器)。
6.web.xml中組件的加載順序?
- context-param -> listener -> filter -> servlet
- 而同個類型之間的實際程序調用的時候的順序是根據對應的 mapping 的順序進行調用的
7.如何確保servlet在應用啓動以後被加載到內存?
- 一般狀況下都是客戶端請求一個servlet,這個servlet纔會被加載到內存,但對於某些很大加載很耗時的servlet咱們但願應用啓動時就加載它們,這時咱們能夠在web.xml文件中配置或者使用webServlet註解(servlet3.0)告訴容器系統一啓動就加載:
<servlet>
<servlet-name>foo</servlet-name>
<servlet-class>com.foo.servlets.Foo</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
- load-on-startup節點中必須配置一個整數,整數表明應用一啓動就會被加載,負數表示當客戶端請求以後才加載,正數的值越小,說明越先被加載。
8.HttpServlet爲何聲明爲抽象類?
- httpServlet類雖然是抽象類但卻沒有抽象方法,之因此這樣設計,是由於doget,dopost等方法並無業務邏輯,開發者至少應該重寫一個service中的方法,這就是咱們不能實例化HttpServlet的緣由。
9.redirect(重定向)和forward(請求轉發)區別?
重定向:
-
兩次請求
-
地址欄發生變化
-
不能夠使用request域的共享數據
-
不能夠訪問/WEB_INF下的資源
轉發:
-
一次請求
-
地址欄不發生變化
-
能夠使用request域的共享數據
-
能夠訪問/WEB_INF下的資源
補充:
servlet中怎麼定義forward 和redirect?
- 轉發:request.getRequestDispatcher (「demo.jsp"). forward(request, response);
- 重定向:response.sendRedirect(「demo.jsp");
10.sevlet中的屬性域有哪些?
servlet提供了一些域對象方便內部servlet之間的通訊,咱們能夠經過set/get方法爲web應用設置或取出屬性值。servlet提供3個域(和jsp區分開來):
- request scope
- session scope
- application scope
分別由ServletRequest,HttpSession,ServletContext對象提供對應的set/get/remove方法去操做者三個域。
注:這跟web.xml中爲servletConfig(針對單個servlet)和servletContext(針對web應用)定義的初始化參數不同。
11.Servlet是否線程安全?
- HttpServlet的init和destroy方法在servlet聲明週期中僅 調用一次,因此不用擔憂它們的線程安全。可是service方法以及doget,dopost等方法是存在線程安全問題的,由於servlet容器爲每個客戶端請求都建立一個線程,這些線程在同一時刻可能訪問同一個servlet的service方法,因此咱們在使用這些方法時務必當心。
12.如何建立線程安全的servlet?(SingleThreadModel方法不算)
- 儘可能使用局部變量,減小全局變量的使用。
- 對於共享變量,加上關鍵字synchronized。
注:servlet中常見線程安全與不安全的對象
- 線程安全:ServletRequest,ServletResponse
- 線程不安全:ServletContext,HttpSession。
對於 ServletContext,咱們應儘可能減小該對象中屬性的修改。
而HttpSession對象在用戶會話期間存在,只能在處理屬於同一個Session的請求的線程中被訪問,所以Session對象的屬性訪問理論上是線程安全的。可是當用戶打開多個同屬於一個進程的瀏覽器窗口,在這些窗口的訪問屬於同一個Session,會出現屢次請求,須要多個工做線程來處理請求,可能形成同時多線程讀寫屬性
13.是否有必要重寫service方法?
- 通常狀況下是沒有必要的,由於service方法會根據請求的類型(get、post等)將請求分發給doxxx方法去執行。即便咱們須要在處理請求以前須要作一些額外的事,咱們也能夠經過過濾器或監聽器完成。
14.servlet包裝類有什麼用?
- servletAPI提供了兩個包裝類:HttpServletRequestWrapper類和HttpServletResponseWrapper類,這些包裝類幫助開發者給出request和response的通常實現。咱們能夠繼承它們並選擇咱們須要複寫的方法進行復寫(包裝設計模式),而不用複寫全部的方法。
15.在servlet中可否產生相似死鎖狀況?
- 能夠的,你在doPost方法中調用doGet方法,在doGet方法中調用doPost方法,將產生死鎖(最終會拋出stackoverflow異常)。
16.Servlet API中forward()與redirect()的區別?
- forward 是服務器轉發,一次請求和響應,瀏覽器地址欄不會顯示出轉發後的地址;forward比較高效,並且有助於隱藏實際地址。
- eg: getServletContext().getRequest Dispatcher(「/servlet/secondservlet」).forward(request, response);
- redirect 是重定向,兩次請求和響應,瀏覽器會獲得跳轉地址,對新地址從新發送請求。
17.ServletContext對象和ServletConfig對象的區別?
- 每一個servlet都會有本身獨有的servletConfig對象而servletContext對象是整個web應用共享的。
- servletConfig提供servlet的初始化參數(init-param),僅該servlet能夠訪問。而servletContext提供的初始化參數整個web應用的全部servlet均可以訪問。
- servletContext對象提供了setAttribute方法設置共享參數,而servletConfig並無對應的set方法。
18.PrintWriter和ServletOutPutStream類有什麼區別?
- PrintWriter是字符流,ServletOutputStream是字節流。能夠經過 PrintWriter向瀏覽器輸出字符數組或者是字符串。也能夠經過ServletOutPutStream向瀏覽器端輸出字節數組。
- PrintWriter對象在servlet中能夠經過response.getWriter()方法獲取
- ServletOutputStream對象經過response.getOutputStream方法獲取。
19.在一個servlet可否同時獲取PrintWriter和ServletOutputStream對象?
- 不能夠,若是同時獲取,將會拋出java.lang.IllegalStateException異常。
20.Request對象的主要方法有哪些?
- setAttribute(String name,Object):設置名字爲name的request 的參數值
- getAttribute(String name):返回由name指定的屬性值
- getAttributeNames():返回request對象全部屬性的名字集合,結果是一個枚舉的實例
- getCookies():返回客戶端的全部Cookie對象,結果是一個Cookie數組
- getCharacterEncoding():返回請求中的字符編碼方式
- getContentLength():返回請求的Body的長度
- getHeader(String name):得到HTTP協議定義的文件頭信息
- getHeaders(String name):返回指定名字的request Header的全部值,結果是一個枚舉的實例
- getHeaderNames():返回因此request Header的名字,結果是一個枚舉的實例
- getInputStream():返回請求的輸入流,用於得到請求中的數據
- getMethod():得到客戶端向服務器端傳送數據的方法
- getParameter(String name):得到客戶端傳送給服務器端的有name指定的參數值
- getParameterNames():得到客戶端傳送給服務器端的全部參數的名字,結果是一個枚舉的實例
- getParametervalues(String name):得到有name指定的參數的全部值
- getProtocol():獲取客戶端向服務器端傳送數據所依據的協議名稱
- getQueryString():得到查詢字符串
- getRequestURI():獲取發出請求字符串的客戶端地址
- getRemoteAddr():獲取客戶端的IP 地址
- getRemoteHost():獲取客戶端的名字
- getSession([Boolean create]):返回和請求相關Session
- getServerName():獲取服務器的名字
- getServletPath():獲取客戶端所請求的腳本文件的路徑
- getServerPort():獲取服務器的端口號
- removeAttribute(String name):刪除請求中的一個屬性
21.jsp和servlet的異同點以及聯繫是什麼?
-
jsp經編譯後就變成了servlet(jsp本質就是servlet,jvm只能識別java的類,不能識別jsp代碼,web容器將jsp的代碼編譯成jvm可以識別的java類)
-
jsp更擅長表現於頁面顯示,servlet更擅長於邏輯控制
-
setvlet中沒有內置對象,jsp中的內置對象都是必須經過HttpServletRequest對象,HttpServletResponse對象及HttpServlet對象獲得
-
jsp是servlet的一種簡化,使用jsp只須要完成程序員需用輸出到客戶端的內容,jsp中的java腳本如何鑲嵌到一個類中,由jsp容器完成,而servlet則是個完整的java類,這個類的service方法用於生成對客戶端的響應
數據庫階段
索引相關
1.什麼是索引?
- 索引是一種數據結構,能夠幫助咱們快速的進行數據的查找
2.索引是個什麼樣的數據結構呢?
- 索引的數據結構和具體存儲引擎的實現有關, 在MySQL中使用較多的索引有Hash索引,B+樹索引等,而咱們常用的InnoDB存儲引擎的默認索引實現爲:B+樹索引.
3.在創建索引的時候,都有哪些須要考慮的因素呢?
- 創建索引的時候通常要考慮到字段的使用頻率,常常做爲條件進行查詢的字段比較適合.若是須要創建聯合索引的話,還須要考慮聯合索引中的順序.此外也要考慮其餘方面,好比防止過多的全部對錶形成太大的壓力.這些都和實際的表結構以及查詢方式有關.
4.關心過業務系統裏面的sql耗時嗎?統計過慢查詢嗎?對慢查詢都怎麼優化過?
在業務系統中,除了使用主鍵進行的查詢,其餘的我都會在測試庫上測試其耗時,慢查詢的統計主要由運維在作,會按期將業務中的慢查詢反饋給咱們.
慢查詢的優化首先要搞明白慢的緣由是什麼? 是查詢條件沒有命中索引?是load了不須要的數據列?仍是數據量太大?
因此優化也是針對這三個方向來的,
-
首先分析語句,看看是否load了額外的數據,多是查詢了多餘的行而且拋棄掉了,多是加載了許多結果中並不須要的列,對語句進行分析以及重寫.
-
分析語句的執行計劃,而後得到其使用索引的狀況,以後修改語句或者修改索引,使得語句能夠儘量的命中索引.
-
若是對語句的優化已經沒法進行,能夠考慮表中的數據量是否太大,若是是的話能夠進行橫向或者縱向的分表.
5.區別B樹,B-,B+,B*?
- B樹:二叉樹,每一個結點只存儲一個關鍵字,等於則命中,小於走左結點,大於走右結點;
- B-樹:多路搜索樹,每一個結點存儲M/2到M個關鍵字,非葉子結點存儲指向關鍵字範圍的子結點; 全部關鍵字在整顆樹中出現,且只出現一次,非葉子結點能夠命中;
- B+樹:在B-樹基礎上,爲葉子結點增長鏈表指針,全部關鍵字都在葉子結點中出現,非葉子結點做爲葉子結點的索引;B+樹老是到葉子結點才命中;
- B*樹:在B+樹基礎上,爲非葉子結點也增長鏈表指針,將結點的最低利用率從1/2提升到2/3;
6.MySQL優化策略?
- 開啓查詢緩存,優化查詢
- explain你的select查詢,這能夠幫你分析你的查詢語句或是表結構的性能瓶頸。EXPLAIN 的查詢結果還會告訴你你的索引主鍵被如何利用的,你的數據表是如何被搜索和排序的
- 當只要一行數據時使用limit 1,MySQL數據庫引擎會在找到一條數據後中止搜索,而不是繼續日後查少下一條符合記錄的數據
- 爲搜索字段建索引
- 使用 ENUM 而不是 VARCHAR,若是你有一個字段,好比「性別」,「國家」,「民族」,「狀態」或「部門」,你知道這些字段的取值是有限並且固定的,那麼,你應該使用 ENUM 而不是VARCHAR。
- Prepared StatementsPrepared Statements很像存儲過程,是一種運行在後臺的SQL語句集合,咱們能夠從使用 prepared statements 得到不少好處,不管是性能問題仍是安全問題。Prepared Statements 能夠檢查一些你綁定好的變量,這樣能夠保護你的程序不會受到「SQL注入式」攻擊
- 垂直分表
- 選擇正確的存儲引擎
7.key和index的區別?
- key 是數據庫的物理結構,它包含兩層意義和做用,一是約束(偏重於約束和規範數據庫的結構完整性),二是索引(輔助查詢用的)。包括primary key, unique key, foreign key 等
- index是數據庫的物理結構,它只是輔助查詢的,它建立時會在另外的表空間(mysql中的innodb表空間)以一個相似目錄的結構存儲。索引要分類的話,分爲前綴索引、全文本索引等;
8.怎麼驗證 mysql 的索引是否知足需求?
- 使用 explain 查看 SQL 是如何執行查詢語句的,從而分析你的索引是否知足需求。
- explain 語法:explain select * from table where type=1。
事務相關
1.ACID是什麼?能夠詳細說一下嗎?
- A=Atomicity
- 原子性,就是上面說的,要麼所有成功,要麼所有失敗.不可能只執行一部分操做.
- C=Consistency
- 系統(數據庫)老是從一個一致性的狀態轉移到另外一個一致性的狀態,不會存在中間狀態.
- I=Isolation
- 隔離性: 一般來講:一個事務在徹底提交以前,對其餘事務是不可見的.注意前面的一般來講加了紅色,意味着有例外狀況.
- D=Durability
- 持久性,一旦事務提交,那麼就永遠是這樣子了,哪怕系統崩潰也不會影響到這個事務的結果.
2.同時有多個事務在進行會怎麼樣呢?
多事務的併發進行通常會形成如下幾個問題:
-
髒讀: A事務讀取到了B事務未提交的內容,而B事務後面進行了回滾.
-
不可重複讀: 當設置A事務只能讀取B事務已經提交的部分,會形成在A事務內的兩次查詢,結果居然不同,由於在此期間B事務進行了提交操做.
-
幻讀: A事務讀取了一個範圍的內容,而同時B事務在此期間插入了一條數據.形成"幻覺".
3.怎麼解決這些問題呢?MySQL的事務隔離級別瞭解嗎?
MySQL的四種隔離級別以下:
-
- 這就是上面所說的例外狀況了,這個隔離級別下,其餘事務能夠看到本事務沒有提交的部分修改.所以會形成髒讀的問題(讀取到了其餘事務未提交的部分,而以後該事務進行了回滾).
- 這個級別的性能沒有足夠大的優點,可是又有不少的問題,所以不多使用.
-
READ COMMITTED(已提交讀)
- 其餘事務只能讀取到本事務已經提交的部分.這個隔離級別有 不可重複讀的問題,在同一個事務內的兩次讀取,拿到的結果居然不同,由於另一個事務對數據進行了修改.
-
REPEATABLE READ(可重複讀)
- 可重複讀隔離級別解決了上面不可重複讀的問題(看名字也知道),可是仍然有一個新問題,就是 幻讀,當你讀取id> 10 的數據行時,對涉及到的全部行加上了讀鎖,此時例外一個事務新插入了一條id=11的數據,由於是新插入的,因此不會觸發上面的鎖的排斥,那麼進行本事務進行下一次的查詢時會發現有一條id=11的數據,而上次的查詢操做並無獲取到,再進行插入就會有主鍵衝突的問題.
-
SERIALIZABLE(可串行化)
- 這是最高的隔離級別,能夠解決上面提到的全部問題,由於他強制將因此的操做串行執行,這會致使併發性能極速降低,所以也不是很經常使用.
4.Innodb使用的是哪一種隔離級別呢?
5.對MySQL的鎖瞭解嗎?
- 當數據庫有併發事務的時候,可能會產生數據的不一致,這時候須要一些機制來保證訪問的次序,鎖機制就是這樣的一個機制.
6.MySQL都有哪些鎖呢?像上面那樣子進行鎖定豈不是有點阻礙併發效率了?
從鎖的類別上來說,有共享鎖和排他鎖.
-
共享鎖: 又叫作讀鎖. 當用戶要進行數據的讀取時,對數據加上共享鎖.共享鎖能夠同時加上多個.
-
排他鎖: 又叫作寫鎖. 當用戶要進行數據的寫入時,對數據加上排他鎖.排他鎖只能夠加一個,他和其餘的排他鎖,共享鎖都相斥.
用上面的例子來講就是用戶的行爲有兩種,一種是來看房,多個用戶一塊兒看房是能夠接受的. 一種是真正的入住一晚,在這期間,不管是想入住的仍是想看房的都不能夠.
鎖的粒度取決於具體的存儲引擎,InnoDB實現了行級鎖,頁級鎖,表級鎖.
他們的加鎖開銷從大到小,併發能力也是從大到小.
7.行級鎖定的優勢缺點?
缺點:
-
-
比頁級或表級鎖定佔用更多的內存。
-
當在表的大部分中使用時,比頁級或表級鎖定速度慢,由於你必須獲取更多的鎖。
-
若是你在大部分數據上常常進行GROUP BY操做或者必須常常掃描整個表,比其它鎖定明顯慢不少。
-
用高級別鎖定,經過支持不一樣的類型鎖定,你也能夠很容易地調節應用程序,由於其鎖成本小於行級鎖定。
8.說一下 mysql 的行鎖和表鎖?
- MyISAM 只支持表鎖,InnoDB 支持表鎖和行鎖,默認爲行鎖。
表設計相關
1. 爲何要儘可能設定一個主鍵?
- 主鍵是數據庫確保數據行在整張表惟一性的保障,即便業務上本張表沒有主鍵,也建議添加一個自增加的ID列做爲主鍵.設定了主鍵以後,在後續的刪改查的時候可能更加快速以及確保操做數據範圍安全.
2.主鍵使用自增ID仍是UUID?
- 推薦使用自增ID,不要使用UUID.
- 由於在InnoDB存儲引擎中,主鍵索引是做爲聚簇索引存在的,也就是說,主鍵索引的B+樹葉子節點上存儲了主鍵索引以及所有的數據(按照順序),若是主鍵索引是自增ID,那麼只須要不斷向後排列便可,若是是UUID,因爲到來的ID與原來的大小不肯定,會形成很是多的數據插入,數據移動,而後致使產生不少的內存碎片,進而形成插入性能的降低.
補充:
- 關於主鍵是聚簇索引,若是沒有主鍵,InnoDB會選擇一個惟一鍵來做爲聚簇索引,若是沒有惟一鍵,會生成一個隱式的主鍵.
3. 字段爲何要求定義爲not null?
- null值會佔用更多的字節,且會在程序中形成不少與預期不符的狀況.
4.varchar(10)和int(10)表明什麼含義?
- varchar的10表明了申請的空間長度,也是能夠存儲的數據的最大長度,而int的10只是表明了展現的長度,不足10位以0填充.也就是說,int(1)和int(10)所能存儲的數字大小以及佔用的空間都是相同的,只是在展現時按照長度展現.
5.建表策略?
-
對於大數據字段,獨立表進行存儲,以便提升性能(例如:簡介字段);
-
使用varchar類型代替char,由於varchar會動態分配長度,char指定長度是固定的;
-
給表建立主鍵,對於沒有主鍵的表,在查詢和索引定義上有必定的影響;
-
避免表字段運行爲null,建議設置默認值(例如:int類型設置默認值爲0)在索引查詢上,效率立顯;
-
創建索引,最好創建在惟一和非空的字段上,創建太多的索引對後期插入、更新都存在必定的影響(考慮實際狀況來建立);
存儲引擎相關
1. MySQL支持哪些存儲引擎?
- MySQL支持多種存儲引擎,好比InnoDB,MyISAM,Memory,Archive等等.在大多數的狀況下,直接選擇使用InnoDB引擎都是最合適的,InnoDB也是MySQL的默認存儲引擎.
2.InnoDB和MyISAM有什麼區別?
-
InnoDB支持事物,而MyISAM不支持事物
-
InnoDB支持行級鎖,而MyISAM支持表級鎖
-
InnoDB支持MVCC, 而MyISAM不支持
-
InnoDB支持外鍵,而MyISAM不支持
-
InnoDB不支持全文索引,而MyISAM支持。
3.什麼是存儲過程?有哪些優缺點?
存儲過程是一些預編譯的SQL語句。一、更加直白的理解:存儲過程能夠說是一個記錄集,它是由一些T-SQL語句組成的代碼塊,這些T-SQL語句代碼像一個方法同樣實現一些功能(對單表或多表的增刪改查),而後再給這個代碼塊取一個名字,在用到這個功能的時候調用他就好了。二、存儲過程是一個預編譯的代碼塊,執行效率比較高,一個存儲過程替代大量T_SQL語句 ,能夠下降網絡通訊量,提升通訊速率,能夠必定程度上確保數據安全
可是,在互聯網項目中,實際上是不太推薦存儲過程的,比較出名的就是阿里的《Java開發手冊》中禁止使用存儲過程,我我的的理解是,在互聯網項目中,迭代太快,項目的生命週期也比較短,人員流動相比於傳統的項目也更加頻繁,在這樣的狀況下,存儲過程的管理確實是沒有那麼方便,同時,複用性也沒有寫在服務層那麼好.
4.說一說三個範式?
- 第一範式: 每一個列都不能夠再拆分.
- 第二範式: 非主鍵列徹底依賴於主鍵,而不能是依賴於主鍵的一部分.
- 第三範式: 非主鍵列只依賴於主鍵,不依賴於其餘非主鍵.
在設計數據庫結構的時候,要儘可能遵照三範式,若是不遵照,必須有足夠的理由.好比性能. 事實上咱們常常會爲了性能而妥協數據庫的設計.