日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java全链路复习面经-基础篇(2.5万字全文)

發(fā)布時間:2024/1/1 java 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java全链路复习面经-基础篇(2.5万字全文) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

序言

主要分為兩篇,一篇基礎(chǔ)篇,涵蓋Java基礎(chǔ),數(shù)據(jù)庫,JVM,計算機網(wǎng)絡(luò)等知識
另一篇為框架篇,主要為流行框架,如Spring、SpringMVC、Mybatis、SpringBoot、SpringCloud、Redis、Linux等知識

文章目錄

  • 序言
  • 基礎(chǔ)篇
      • 談?wù)剬γ嫦驅(qū)ο笏枷氲睦斫?/li>
      • JDK,JRE,JVM有什么區(qū)別?
      • Java的基本數(shù)據(jù)類型有哪些?
      • ==和equals的區(qū)別 | &和&&的區(qū)別
      • final的作用
      • String,StringBuffer,StringBuilder區(qū)別
      • String s = "java"與String s = new String("java")
      • 接口和抽象類的區(qū)別
      • 算法題-求N的階乘
      • 什么是向上轉(zhuǎn)型?什么是向下轉(zhuǎn)型?
      • Int和Integer的區(qū)別(重點)
      • 方法的重寫和重載的區(qū)別
      • List和Set的區(qū)別
      • 談?wù)凙rrayList和LinkedList的區(qū)別
      • 如何在雙向鏈表A和B之間插入C
      • Object類中的方法介紹
      • equals()與 hashcode() 的區(qū)別
      • 除了NEW還有什么創(chuàng)建類的方式
      • Exception 和 Error 的區(qū)別
      • 反射原理及使用場景
      • Java會發(fā)生內(nèi)存泄漏問題嗎?有哪些場景會發(fā)生內(nèi)存泄漏
      • ArrayList的擴容機制
      • ConcurrentHashMap 的 put 方法過程
      • HashMap的擴容機制
      • 為什么HashMap長度都是2的次冪
      • HashMap為什么使用紅黑樹而不使用別的樹?
      • 為什么鏈表長度大于閾值 8 時才將鏈表轉(zhuǎn)為紅黑樹?
      • CopyOnWriteArrayList
      • Servlet和Filter的區(qū)別
      • 悲觀鎖和樂觀鎖
      • CAS
      • Java對象頭存放什么內(nèi)容
      • Volatile 關(guān)鍵字以及底層實現(xiàn)
      • 線程池,線程池的作用
      • AQS
      • 談?wù)凥ashSet的存儲原理
      • 談?wù)凩inkedHashMap和HashMap的區(qū)別(重點)
      • 談?wù)凜oncurrentHashMap,HashMap,Hashtable的區(qū)別
      • ArrayList vs Vector vs CopyOnWriteArrayList
      • 開發(fā)一個自己的棧,你會怎么寫?
      • 補充:集合知識小結(jié)
      • 談?wù)処O流的分類及選擇
      • serialVersionUID的作用是什么
      • 請描述下Java的異常體系
      • 羅列常見的5個運行時異常和非運行時異常
      • throw跟throws的區(qū)別
      • 一道關(guān)于try catch finally返回值的問題
      • 創(chuàng)建線程的方式
      • 一個普通main方法的執(zhí)行,是單線程模式還是多線程模式?為什么
      • 請描述線程的生命周期
      • 談?wù)勀銓hreadLocal的理解
      • 談?wù)凙Jax的工作原理
      • 談?wù)凷ervlet的生命周期
      • 描述Session跟Cookie的區(qū)別(重要)
      • 補 Get請求與Post請求的區(qū)別
      • 轉(zhuǎn)發(fā)和重定向的區(qū)別
      • Iterator和ListIterator的區(qū)別?
      • 并發(fā)和并行的區(qū)別
      • 什么是序列化?
      • 說說synchronized底層原理
      • synchronized和volatile的區(qū)別
      • synchronized和lock的區(qū)別
      • 什么是死鎖?如何防止死鎖?
      • 什么是反射?可以解決什么問題?
      • 什么是悲觀鎖,什么是樂觀鎖?
    • 數(shù)據(jù)庫說明
      • 談?wù)剶?shù)據(jù)庫設(shè)計的三大范式及反范式
      • 左連接,右連接,內(nèi)連接,如何編寫SQL,他們的區(qū)別是什么?
      • 如何解決SQL注入?
      • JDBC如何實現(xiàn)對事務(wù)的控制及事務(wù)邊界
      • 談?wù)勈聞?wù)的特點
      • 談?wù)勈聞?wù)的隔離級別
      • InnoDB是如何支持事務(wù)的 ?
      • 介紹一下MVCC
      • 索引如何避免全表掃描(索引失效)
      • 最左前綴
      • 查詢很慢怎么解決 ?
    • 計算機網(wǎng)絡(luò)
      • 說說TCP和UDP的區(qū)別
      • TCP/IP協(xié)議基礎(chǔ)
      • 計算機網(wǎng)絡(luò)層次
      • SSL概述
      • HTTP 和 HTTPS 的區(qū)別
      • 談?wù)勈裁词荰CP的三次握手,可不可以只握手兩次?
      • 談?wù)勈裁词荰CP的四次揮手?
      • 瀏覽器輸入 URL 并回車的過程以及相關(guān)協(xié)議,DNS 查詢過程
    • JVM虛擬機
      • JVM內(nèi)存區(qū)域是怎么劃分的?
      • 說說JVM的運行時內(nèi)存
      • 談?wù)劺厥账惴?/li>
      • 四種引用類型
      • 垃圾回收器
      • Full GC 觸發(fā)條件
      • 對象創(chuàng)建過程
      • 對象已經(jīng)死亡
      • 類的加載過程
      • 談?wù)勵惣虞d過程的雙親委托機制?
      • JVM的內(nèi)存模型
      • JVM性能調(diào)優(yōu)常用命令

基礎(chǔ)篇

談?wù)剬γ嫦驅(qū)ο笏枷氲睦斫?/h3>

面向?qū)ο笫且环N編程思想。面向?qū)ο蟪绦蛟O(shè)計的核心思想是以對象為核心。除了面向?qū)ο笾膺€有面向過程,二者是兩種不同的開發(fā)思想。

當(dāng)我們需要完成生成隨機數(shù)這一個功能時,如果是以面向過程的思想進行開發(fā),則更加專注于設(shè)計的這個實現(xiàn)的算法;但是以面向?qū)ο蟮奶匦詠硗瓿蛇@個功能時,我們更強調(diào)的是對象,通過找一個能夠生成隨機數(shù)功能的對象來幫我們完成(如Random),作為開發(fā)者并不需要關(guān)注這個代碼是怎么實現(xiàn)的,找到合適的對象,然后調(diào)用對象的方法即可。

面向?qū)ο蟮乃拇筇匦?#xff1a;封裝、集成、多態(tài)、抽象

封裝性:封裝簡單的說就是將細節(jié)隱藏起來,外界只管調(diào)用,無需在意細節(jié),這也提高了程序的安全性;在Java當(dāng)中最常見的兩個封裝就是定義方法、private關(guān)鍵字,其中定義一個類,也是封裝。

繼承:就是從已有的類中得到繼承關(guān)系的過程。通過繼承,能夠使得代碼在保持原有基礎(chǔ)上,能得到更多拓展。通常將對象的共有特征進行抽取得到父類。

  • 父類和子類的關(guān)系:子類也是父類。如,講師、助教也是屬于員工的范疇。
  • this代指當(dāng)前的對象,而super代指父類對象(超類)

多態(tài):是指運行不同子類型的對象對同一消息作出不同的響應(yīng)。

講師和助教都屬于員工,他們都有共同的行為,如:工作。但是講師的工作是上課,助教的工作是幫助教學(xué),雖然他們都是工作,但是工作內(nèi)容是不一樣的

多態(tài)的格式:超類型的引用指向派生類 或 父類型的引用指向子類

//類: 父類 對象名 = new 子類() Employee one = new Teacher(); //此時將教師向上轉(zhuǎn)型為員工 //接口: 接口 接口名 =new 接口的實現(xiàn)類()

使用多態(tài)的最大好處就是能夠降低代碼的耦合性;

JDK,JRE,JVM有什么區(qū)別?

分別是都是三個單詞的縮寫

JDK: Java Development Kit ,指的是Java開發(fā)的工具包,提供了Java開發(fā)環(huán)境和運行環(huán)境

JRE:Java Runtime Environment,Java運行環(huán)境,包含Java虛擬機及一些基礎(chǔ)類庫

JVM:Java Virtual Machine,Java虛擬機,提供執(zhí)行字節(jié)碼文件的能力

JVM實現(xiàn)跨平臺的流程:

將編寫好的.java文件進行編譯成.class文件,此時不同平臺的JVM就會去運行這個.class文件,從而實現(xiàn)跨平臺的特性。

Java的基本數(shù)據(jù)類型有哪些?

整形:byte、short、int、long

浮點型:double,float

布爾型:boolean

字符型:char

一共八種基本數(shù)據(jù)類型。

String是引用類型

以下是占用字節(jié)情況:

名稱占用字節(jié)
byte1
short2
int4
long8
double8
float4
char2

==和equals的區(qū)別 | &和&&的區(qū)別

==和equals的區(qū)別:

  • == 是比較運算符,equals是Object的一個方法

  • == 在比較在基本類型使用中,是判斷數(shù)值是否相等,而在比較引用類型時,則比較引用類型的地址值是否相等

  • equals是用于比較內(nèi)容是否相等,但是在Object的源碼當(dāng)中可以發(fā)現(xiàn)其實內(nèi)部也是使用 == 運算符的

public boolean equals(Object obj) { return (this == obj); }

因此在沒有重寫equals方法前,它的作用是與 == 一樣的。

為了實現(xiàn)內(nèi)容相同,通常需要對equals進行重寫,如String類就對該方法進行了重寫,從而實現(xiàn)了內(nèi)容上的比對。

以下是String類重寫了equals的源碼

public boolean equals(Object anObject) {if (this == anObject) {//判斷是否是當(dāng)前對象return true;//是同一個對象的話就返回true}if (anObject instanceof String) {//判斷是否都是String類或子類 String anotherString = (String)anObject;//是的話就對內(nèi)容就行逐個比對int n = value.length;if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}//不是當(dāng)前類或子類或接口實現(xiàn)類,就返回false;return false;}

&和&&的區(qū)別:

&和&&都能夠進行邏輯與運算

if(a==b && a>0) //當(dāng)左邊a==b的結(jié)果為false時,會直接短路掉右邊,因此右邊的a>0是不會繼續(xù)執(zhí)行的 if(a==b & a>0) //當(dāng)左邊a==b的結(jié)果為false時,不會短路掉右邊,因此右邊的a>0會繼續(xù)執(zhí)行的

final的作用

final的中文意譯為 最終的;最后的

因此被final修飾的類、方法、變量也都是’最終的

也就是說:

  • 被final修飾的變量為常量,不可再變。
  • 被final修飾的方法不可以被重寫
  • 被final修飾的類不可以再變,也不能被繼承。

如果修飾的是引用變量,則引用變量的地址值不能發(fā)生改變。

但是可以修飾該變量下類的屬性。

//例如 final Person person = new Person(30,"tomcat"); //此時仍然可以對Person的屬性進行賦值 person.setAge(35);

String,StringBuffer,StringBuilder區(qū)別

查看源碼可以發(fā)現(xiàn),String類在內(nèi)部使用了final關(guān)鍵字,因此一旦創(chuàng)建對象就意味著不可以改變自身,在重新賦值時等于重新生成了一個新的字符串對象。

StringBuffer是可以改變自身對象的,因此在推薦在需要經(jīng)常對字符串內(nèi)容的場景下使用。

線程安全性

String是由final修飾的,定義后對象的內(nèi)容不可變,因此是線程安全的。

StringBuffer在內(nèi)部的方法下加入了syschronized,執(zhí)行的效率低,但是是線程安全的。

StringBuilder跟StringBuffer一樣,區(qū)別在于StringBuilder沒有使用同步鎖,執(zhí)行效率高,是線程不安全的類。

String s = "java"與String s = new String(“java”)

通過第一種形式:String s = "java"來得到的引用類型s,此時JVM會將這個變量放入常量池當(dāng)中,當(dāng)有別的變量的值也為’java’時,就會共享這一份String

通過String snew = new String(“java”)這種形式得到的變量snew ,是通過new的形式得到的,此時會在虛擬機的堆內(nèi)存中開辟內(nèi)存空間。

一道關(guān)于String和數(shù)組的筆試題

public static void main(String[] args) {int[] a = {1,2,3,4,5};String str = "abc";test(a,str);System.out.print(str+" and ");System.out.println(Arrays.toString(a));}private static void test(int[] a, String str) {a[0] = 10;str = "def";}

顯示的結(jié)果為?

abc and [10, 2, 3, 4, 5]

在JVM運行時內(nèi)存區(qū)域中,變量參數(shù)存在棧中,new出來的對象或數(shù)組存放在堆中。

在Java當(dāng)中方法參數(shù)傳遞為值傳遞,當(dāng)傳遞的參數(shù)是基本類型時,就把基本類型的值傳遞給方法;當(dāng)傳遞的參數(shù)是引用類型時,此時會把對象在堆內(nèi)存中的引用地址傳遞給方法

當(dāng)把字符串和數(shù)組當(dāng)參數(shù)調(diào)用方法時,實際傳遞的是其在堆內(nèi)存中的地址,如此處為 0x666、0x999

因此當(dāng)修改數(shù)組時,實際就是修改該堆內(nèi)存的數(shù)組

然而,String為final修飾的內(nèi)容,實際上是不可以更改的,因此仍然顯示“abc”

接口和抽象類的區(qū)別

抽象類與接口之間的區(qū)別

從語法來說:

  • 抽象類:方法可以有抽象的,也可以有非抽象, 有構(gòu)造器

    • 接口:方法都是抽象,屬性都是常量,默認有public static final修飾
  • JDK1.8之后:

  • 接口里面可以有實現(xiàn)的方法,注意要在方法的聲明上加上default或者static

從開發(fā)的角度:

抽象類

抽象類可以有抽象方法也可以有具體的方法,如在MVC三層架構(gòu)中,Dao層編寫多個UserDao,此時可以抽象類,抽取常用的CRUD方法作為每一個dao的通用方法,而需要同一個方法的不同實現(xiàn)時,就在抽象類中編寫抽象方法。

接口

接口更像是一種開發(fā)的規(guī)范,雖然在JDK1.8之后也可以寫實例方法,但是一般不這么采用。

在MVC三層架構(gòu)的實際開發(fā)中,service調(diào)用dao,開發(fā)中需要將實現(xiàn)類注入到IOC容器當(dāng)中,實際調(diào)用是由接口調(diào)用,由接口指向?qū)崿F(xiàn)類。

當(dāng)接口的實現(xiàn)類不能滿足功能時,可以隨時將新的實現(xiàn)類注入到IOC容器中,由于是用接口調(diào)用實現(xiàn)類,此時接口作為一個種規(guī)范,并不需要調(diào)整相關(guān)的代碼,從而實現(xiàn)低耦合高內(nèi)聚的目的

算法題-求N的階乘

遞歸就是自己調(diào)用自己,在JVM中每調(diào)用一次方法就會將該方法壓入棧內(nèi),調(diào)用的次數(shù)過多還未來得及出棧,此時就會發(fā)送溢?!獥?nèi)存溢出,所以遞歸的次數(shù)不能過多。

做遞歸題重要的就是要找到跳出遞歸的突破口

public class DgTest {public static void main(String[] args) {Integer integer = test01(10);System.out.println("結(jié)果為"+integer);}/*** 使用遞歸計算n的階乘*/public static Integer test01(Integer count){if(count <= 0){throw new RuntimeException("非法參數(shù)");}if(count==1){return 1;}return test01(count-1)*count;}}

總結(jié)遞歸調(diào)用:

  • 遞歸調(diào)用要注意出口位置
  • 遞歸調(diào)用次數(shù)不要過多,防止棧內(nèi)存溢出

什么是向上轉(zhuǎn)型?什么是向下轉(zhuǎn)型?

向上向下轉(zhuǎn)型發(fā)生在父子類當(dāng)中。

如醫(yī)生和老師都是繼承于員工類,員工又繼承于Object類,此時的關(guān)系如圖所示。

當(dāng)類的類型又Object往下變化時,就為向上轉(zhuǎn)型,反之則為向上轉(zhuǎn)型。

用代碼的形式描述:

Employee teacher = new Teacher();//由Teacher向上轉(zhuǎn)型為Employee Docter docter = new Employee();//由Employee向下轉(zhuǎn)型為Docter

在繼承的描述關(guān)系中,A繼承于B,也可以稱B就是A;所以我們可以說醫(yī)生、老師就是員工,員工就是Object。因此發(fā)生向下轉(zhuǎn)型時,是不會報錯的。

但是反過來,員工可以有很多種,既可以為老師也可以為醫(yī)生,如果需要向下轉(zhuǎn)型, 如果父類不能確定是指定的子類,則父類是不可以隨意轉(zhuǎn)型為子類的,不然就會報 ClassCastException 。

因此在需要向下轉(zhuǎn)型時,需要先用instanceof來判斷是否是子類。

Employee employee = new Docter(); if(employee instanceof Docter){ Docter docter = new Employee();//由Employee向下轉(zhuǎn)型為Docter }

Int和Integer的區(qū)別(重點)

看以下例子:

Integer a = new Integer(3);Integer b = 3; //自動裝箱,會調(diào)用Integer的valueOf()方法int c = 3;System.out.print(a==b);//false,new出來的對象在堆內(nèi)存中會開辟新的空間System.out.print(a==c);//true,a會自動拆箱為int,然后跟c進行比較

自動裝箱:Integer型的對象直接賦值一個int數(shù)值時,會自動調(diào)用Integer的valueOf()方法,將int轉(zhuǎn)換為Integer;

自動拆箱:當(dāng)一個Integer與int進行比較時,Integer類型的對象會自動拆箱為int,然后跟c進行比較。

以下例子:

Integer i3 = 126;Integer i4 = 126; System.out.println(i3 == i4);//true ---------------------- Integer i6 = 128; Integer i7 = 128; System.out.println(i6 == i7);//false

以上兩個例子都是自動裝箱,因此都會自動調(diào)用Integer的valueOf()方法,但是兩個結(jié)果卻是不一樣的。

翻看valueOf的源碼:

static final int low = -128;static final int high = 127;public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high)//先進行范圍比較 //如果在[-128,127]之間,就從緩存中返回 return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);//否則就直接new}

可以看到首先會對i進行范圍篩選,如果是在[-128,127],就會將常量池中的對象返回,否則就會new新的對象。

當(dāng)取值在這個范圍內(nèi)時就是true,否則就是false

方法的重寫和重載的區(qū)別

重載發(fā)生在一個類中,同名的方法如果有不同的參數(shù)列表則視為重載。與返回值類型無關(guān)

以下不構(gòu)成重載public double add(int a,int b)public int add(int a,int b)

重寫發(fā)發(fā)生在子類和父類之間,重寫要求子類的重寫方法與父類的方法有相同的方法名、參數(shù)列表。返回值類型也要一致

注意:

  • 重載與方法的返回值無關(guān),存在于父類和子類以及同一個類中
  • 在父子類中,構(gòu)造方法不能被重寫,被final、static修飾的類不能重寫

List和Set的區(qū)別

最直觀的區(qū)別就是

LIST是有序的,可以存儲重復(fù)元素

SET是無序的,不可以存儲重復(fù)元素。

補充:

list包含有

  • ArrayList:底層是數(shù)組,查詢,快連續(xù)內(nèi)存空間方便尋址;增刪慢,會發(fā)送數(shù)據(jù)遷移?!?strong>是線程不安全類
  • LinkList:底層是雙向鏈表,查詢慢,需要通過指針尋找,增刪快,改變其前后節(jié)點即可。—是線程不安全類
  • vertor:底層是數(shù)組,查詢快,增刪慢—是線程安全類

set包含有:

  • HashSet:底層使用Hash排序,先比對Hash值,如果Hash值一樣再比對內(nèi)容是否一致
  • TreeSet:會對Set的內(nèi)容進行排序

set因為使用HashMap作為底層,因此是線程不安全的。

**TreeSet是指排序,set的無序是指存入取出的順序不一樣 **

談?wù)凙rrayList和LinkedList的區(qū)別

學(xué)過數(shù)據(jù)結(jié)構(gòu)的話應(yīng)該很容易明白,其實就是數(shù)組和鏈表之間的區(qū)別。

ArrayList底層是數(shù)組,會在內(nèi)存中開辟一段連續(xù)空間,增刪慢,查找快——不夠嚴謹?shù)谋硎?/p>

LinkedList底層是雙向鏈表,在內(nèi)存中的空間是不連續(xù)的,特點是增刪快,查找慢——不夠嚴謹?shù)谋硎?/p>

嚴謹表述

數(shù)組的增刪慢也有特殊情況,如果在數(shù)組的頭部和尾部進行增改刪操作的話這個速度也是不慢的。

LinkedList使用了雙向鏈表,在頭部和尾部都有指針,因此當(dāng)訪問頭部和尾部時,速度也是不慢的。

ArrayList和LinkList查詢和增刪速度的說明

當(dāng)進行查找時,ArrayList底層使用數(shù)組,在內(nèi)部開辟了連續(xù)的內(nèi)存空間,因此當(dāng)需要按位序查找時,速度比LinkList快是沒的說的,但是當(dāng)需求發(fā)送變化,如果是按值查找,此時二者都需要進行遍歷查找,二者的速度就顯得半斤八兩。

當(dāng)進行增刪操作時,如果發(fā)生的位置在集合的中間部分,由于ArrayList需要對數(shù)據(jù)進行遷移,而LinkList在內(nèi)存當(dāng)中只需要更改指針位置,此時LinkList在增刪操作時是有很大優(yōu)勢的。但如果是對末尾進行增刪操作,ArrayList不需要做數(shù)據(jù)遷移(未超出數(shù)組長度),LinkList為雙向鏈表,此時二者的速度也是半斤八兩。

ArrayList的擴容機制

ArrayList初始的數(shù)組長度為10,當(dāng)對集合的操作達到預(yù)警值時,就會將創(chuàng)建新數(shù)組,通過位運算,將數(shù)組的長度擴大為原數(shù)組的1.5倍,之后將原數(shù)組的數(shù)據(jù)遷移到新數(shù)組當(dāng)中。

如何在雙向鏈表A和B之間插入C

一個數(shù)據(jù)結(jié)構(gòu)的題目。—> 雙鏈表A、B節(jié)點之間插入一個C節(jié)點

雙鏈表:一個節(jié)點由三個部分組成,分別為前置指針、數(shù)據(jù)、后置指針。

前后指針分別指向前一個節(jié)點、后一個節(jié)點的地址值。

偽代碼:

c.next = a.next;a.next.pre = c;a.next = c;c.pre = a;

Object類中的方法介紹

public final native Class<?> getClass();

getClass使用了native 方法,內(nèi)部使用了C/C++實現(xiàn),用于返回當(dāng)前運行時對象的 Class 對象

public native int hashCode();

hashCode用于返回對象的哈希碼,重寫了Equals方法就需要重寫hashCode方法

public boolean equals(Object obj) {return (this == obj);}

equals用于比較 2 個對象的內(nèi)存地址是否相等,在需要比較內(nèi)容是否相同時需要重寫該方法

protected native Object clone() throws CloneNotSupportedException;

tclone方法hrows CloneNotSupportedException//naitive 方法,用于創(chuàng)建并返回當(dāng)前對象的一份

public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());}

toString返回類的名字@實例的哈希碼的 16 進制的字符串。建議 Object 所有的子類都重寫這個方法。

public final native void notify()

notify()使用了native 方法,并且不能重寫。喚醒一個在此對象監(jiān)視器上等待的線程(監(jiān)視器相當(dāng)于就是鎖的概念)。如果有多個線程在等待只會任意喚醒一個。

public final native void notifyAll()

notifyAll()使用了native 方法,并且不能重寫。跟 notify 一樣,唯一的區(qū)別就是會喚醒在此對象監(jiān)視器上等待的所有線程,而不是一個線程。

public final native void wait(long timeout) throws InterruptedException

native 方法,并且不能重寫。暫停線程的執(zhí)行。注意:sleep 方法沒有釋放鎖,而 wait 方法釋放了鎖 。timeout 是等待時間。

protected void finalize() throws Throwable { }

finalize方法表示實例被垃圾回收器回收的時候觸發(fā)的操作

equals()與 hashcode() 的區(qū)別

hashCode介紹:

hashCode() 的作用是獲取哈希碼,也稱為散列碼;它實際上是返回一個 int 整數(shù)。這個哈希碼的作用是確定該對象在哈希表中的索引位置。hashcode 方法是本地方法,也就是用 c 語言或 c++ 實現(xiàn)的,該方法通常用來將對象的 內(nèi)存地址轉(zhuǎn)換為整數(shù)之后返回。

為什么重寫 equals 時必須重寫 hashCode 方法

如果兩個對像是相等的,它的哈希嗎一定也是相同的,此時調(diào)用equals方法也能返回true,但是哈希碼相同的對象它們不一定會相等;

當(dāng)我們重寫equals時,判斷對象是否相等的邏輯有原來的==變?yōu)榱伺袛鄬傩允欠褚恢?#xff0c;因此為了對象的一致性,就必須重寫hashCode方法

重寫equals時,是為了用自身的方式去判斷兩個自定義對象是否相等,然而如果此時剛好需要我們用自定義的對象去充當(dāng)hashmap的健值使用時,就會出現(xiàn)我們認為的同一對象,卻因為hash值不同而導(dǎo)致hashmap中存了兩個對象,從而才需要進行hashcode方法的覆蓋。

什么情況下可以不重寫 hashCode ?

當(dāng)所在類不使用 HashSet、Hashtable、HashMap 等散列集合進行存儲的時候,可以不使用 hashcode。

除了NEW還有什么創(chuàng)建類的方式

創(chuàng)建類的方式:

  • 使用new關(guān)鍵字來創(chuàng)建類
  • 使用反射來創(chuàng)建類
  • 使用反序列化來創(chuàng)建類
  • 使用反射來創(chuàng)建類

    public void test(){ String str = "com.smoyu.blog.Test"; Class class = Class.forName(str); Test t = (Class)class.newInstance(); }

    Exception 和 Error 的區(qū)別

    Error 類和 Exception 類的父類都是父類都是 throwable 類

    Error 類一般是指與虛擬機相關(guān)的問題,如系統(tǒng)崩潰,虛擬機錯誤,內(nèi)存空間不足方法調(diào)用棧溢出等。對于這類錯誤的導(dǎo)致的應(yīng)用程序中斷,僅靠程序本身無法恢復(fù)和和預(yù)防**,遇到這樣的錯誤,建議讓程序終止。

    Exception 類表示程序可以處理的異常可以捕獲且可能恢復(fù)。遇到這類異常,應(yīng)該盡可能處理異常,使程序恢復(fù)運行,而不應(yīng)該隨意終止異常。

    反射原理及使用場景

    Java 反射機制是在運行狀態(tài)中,對于任意一個類可以知道它的所有屬性和方法;對于任意一個對象,可以調(diào)用它的所有屬性和方法;這種動態(tài)獲取信息以及動態(tài)調(diào)用對象的方法的功能稱為 Java 的反射機制。

    使用反射機制的前提條件是獲得代表的字節(jié)碼的 Class 文件兩種方式):

    1.知道具體類的情況下可以使用:

    Class alunbarClass = TargetObject.class;

    但是我們一般是不知道具體類的,基本都是通過遍歷包下面的類來獲取 Class 對象

    2.通過 Class.forName()傳入類的路徑獲取:

    Class alunbarClass1 = Class.forName(“cn.javaguide.TargetObject”);

    **優(yōu)缺點:優(yōu)點:**運行期類型的判斷,動態(tài)加載類,提高代碼靈活度。

    缺點

  • 性能瓶頸:反射相當(dāng)于一系列解釋操作,通知 JVM 要做的事情,性能比直接的 java 代碼要慢很多。
  • 安全問題,讓我們可以動態(tài)操作改變類的屬性同時也增加了類的安全隱患。
  • 應(yīng)用場景:

  • JDBC 連接數(shù)據(jù)庫時使用 Class.forName()通過反射加載數(shù)據(jù)庫的驅(qū)動程序;
  • Spring 框架的 IOC(動態(tài)加載管理 Bean)創(chuàng)建對象以及 AOP(動態(tài)代理)功能都和反射有聯(lián)系;
  • 動態(tài)配置實例的屬性;
  • Java會發(fā)生內(nèi)存泄漏問題嗎?有哪些場景會發(fā)生內(nèi)存泄漏

    舉例部分常用場景:

  • 使用單例模式也有可能造成內(nèi)存泄漏,這是因為單例模式 static 的對象是存放在方法區(qū)中的。不會被回收。
  • 沒有釋放的資源連接,如數(shù)據(jù)庫連接、網(wǎng)絡(luò)連接等。這種資源的連接只有代碼中顯示的調(diào)用 close()才能夠關(guān)閉資源,如果沒有調(diào)用 close()方法,資源連接是不會被 GC 垃圾回收器回收的。
  • ArrayList的擴容機制

    總結(jié):ArrayList底層源碼是基于數(shù)組來實現(xiàn)的,并且默認初始的容量為10,擴容時使用位運算的形式,每次以原size的1.5倍創(chuàng)建新數(shù)組,通過調(diào)用 elementData = Arrays.copyOf(elementData, newCapacity); 將原數(shù)據(jù)移動到新數(shù)組中

    源碼分析:

    transient Object[] elementData; // 定義一個數(shù)組private int size;/*** Default initial capacity.*/private static final int DEFAULT_CAPACITY = 10;//初始容量為10

    get(int index)方法:

    public E get(int index) {rangeCheck(index); //檢查數(shù)組是否越界return elementData(index);//直接返回數(shù)組的下標}

    當(dāng)調(diào)用add(E e) 方法時,會判斷是否擴容

    public boolean add(E e) {ensureCapacityInternal(size + 1); // 判斷是否需要擴容elementData[size++] = e; //執(zhí)行添加操作return true;}

    此時,add方法中調(diào)用了ensureCapacityInternal(size + 1); ,繼續(xù)翻閱該方法

    private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); //此處嵌套了兩個方法}

    此時又繼續(xù)調(diào)用方法ensureExplicitCapacity方法,且內(nèi)部執(zhí)行了calculateCapacity用于擴容

    private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0) //判斷是否需要執(zhí)行擴容,如果該長度大于數(shù)組的長度,就執(zhí)行擴容,且每次擴容按1.5進行grow(minCapacity); } private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;}

    最終調(diào)用了grow方法

    private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); //if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:elementData = Arrays.copyOf(elementData, newCapacity); }

    此處第三四行代碼:

    • int oldCapacity = elementData.length;
    • int newCapacity = oldCapacity + (oldCapacity >> 1); //

    oldCapacity >> 1)執(zhí)行了右移操作,相當(dāng)于 oldCapacity / 2

    這里就是擴容大小確定的地方,相當(dāng)于新的最大容量是 舊的數(shù)組長度+舊數(shù)組的0.5長度

    ConcurrentHashMap 的 put 方法過程

    • 根據(jù) key 計算出 hashcode 。
    • 判斷數(shù)組桶是否為空,為空則初始化數(shù)組桶。
    • 即為當(dāng)前 key 定位出的 Node,如果為空表示當(dāng)前位置可以寫入數(shù)據(jù),利用 CAS 嘗試寫入,失敗則自旋保證成功。
    • 如果當(dāng)前位置的 hashcode == MOVED == -1,則需要進行擴容。
    • 如果都不滿足,則利用 synchronized 鎖寫入數(shù)據(jù)。判斷是否為鏈表,為鏈表則遍歷鏈表加入新數(shù)據(jù),如果相等則
    • 覆蓋節(jié)點。判斷為紅黑樹,則進行一個紅黑樹的插入。
    • 如果數(shù)量大于 TREEIFY_THRESHOLD 則要轉(zhuǎn)換為紅黑樹。

    HashMap的擴容機制

    1、首先判斷 OldCap 有沒有超過最大值。

    2、當(dāng) hashmap 中的元素個數(shù)超過數(shù)組大小*loadFactor 時,就會進行數(shù)組擴容,loadFactor 的默認值為 0.75,也就是說,默認情況下,數(shù)組大小為 16,那么當(dāng) hashmap中元素個數(shù)超過 160.75=12的時候,就把數(shù)組的大小擴展為 216=32,即擴大一倍。

    3、然后重新計算每個元素在數(shù)組中的位置,而這是一個非常消耗性能的操作,所以如果我們已經(jīng)預(yù)知 hashmap 中元素的個數(shù),那么預(yù)設(shè)元素的個數(shù)能夠有效的提高 hashmap 的性能。比如說,我們有 1000 個元素 new HashMap(1000), 70但是理論上來講 new HashMap(1024)更合適,不過上面已經(jīng)說過,即使是 1000,hashmap 也自動會將其設(shè)置為 1024。但是 new HashMap(1024)還不是更合適的,因為 0.751000 < 1000, 也就是說為了讓 0.75 size > 1000, 我們必須這樣new HashMap(2048)才最合適,既考慮了&的問題,也避免了 resize 的問題。

    為什么HashMap長度都是2的次冪

    原因在于當(dāng)長度是2次冪時滿足以下公式:

    hash%length==hash&(length-1)

    使用& 運算的速度比直接取余更快。

    HashMap為什么使用紅黑樹而不使用別的樹?

    因為紅黑樹不追求完美的平衡,只要求達到部分平衡,可以減少增刪結(jié)點時的左旋轉(zhuǎn)和右旋轉(zhuǎn)的次數(shù)

    為什么鏈表長度大于閾值 8 時才將鏈表轉(zhuǎn)為紅黑樹?

    因為樹結(jié)點占用的存儲空間是普通結(jié)點的兩倍。因此紅黑樹比鏈表更加耗費空間。結(jié)點較少的時候,時間復(fù)雜度上鏈表不會比紅黑樹高太多,但是能大大減少空間。

    當(dāng)鏈表元素個數(shù)大于等于 8 時,鏈表換成樹結(jié)構(gòu);若桶中鏈表元素個數(shù)小于等于 6 時,樹結(jié)構(gòu)還原成鏈表。因為紅黑樹的平均查找長度是 log(n),長度為 8 的時候,平均查找長度為 3,如果繼續(xù)使用鏈表,查找長度為 8/2=4,這才有轉(zhuǎn)換為樹的必要。

    CopyOnWriteArrayList

    它的實現(xiàn)就是寫時復(fù)制,在往集合中添加數(shù)據(jù)的時候,先拷貝存儲的數(shù)組然后添加元素到拷貝好的數(shù)組中,然后用現(xiàn)在的數(shù)組去替換成員變量的數(shù)組(就是 get 等讀取操作讀取的數(shù)組)。這個機制和讀寫鎖是一樣的,但是比讀寫鎖有改進的地方,那就是讀取的時候可以寫入的 ,這樣省去了讀寫之間的競爭,同時寫入的時候怎么辦呢?當(dāng)然果斷還是加鎖。

    適用場景:copyonwrite 的機制雖然是線程安全的,但是在 add 操作的時候不停的拷貝是一件很費時的操作,所以使用到這個集合的時候盡量不要出現(xiàn)頻繁的添加操作,而且在迭代的時候數(shù)據(jù)也是不及時的,數(shù)據(jù)量少還好說,數(shù)據(jù)太多的時候,實時性可能就差距很大了。在多讀取,少添加的時候,他的效果還是不錯的(數(shù)據(jù)量大無所謂,只要你不添加,他都是好用的)。

    CopyOnWriteArrayList 的 get 方法:get 的方法就是普通集合的 get 沒有什么特殊的地方,但是成員變量的聲明還是有講究的,是個用 volatile 聲明的數(shù)組,這樣就保證了讀取的那一刻讀取的是最新的數(shù)據(jù)。

    CopyOnWriteArrayList 的 add 方法: add 方法了,可以明顯看出是明顯需要 reentrantlock 加鎖的,接下來就是復(fù)制數(shù)據(jù)添加數(shù)據(jù)的過程,在 setArray 的過程中,把新的數(shù)組賦值給成員變量 array(這里是引用的指向,java 保證賦值的過程是一個原子操作)。

    Servlet和Filter的區(qū)別

    作用不同

    Servlet 是一個運行在 web 服務(wù)端的 java 程序, 用于接收和響應(yīng)請求。我們通常寫的各種 Java Web 應(yīng)用本質(zhì)上就是一個 Servlet 程序。

    Tomcat 是一個 Servlet 容器,用于部署 Serlvet 程序。

    Filter 是一個運行在 web 服務(wù)端的 java 程序, 用于攔截請求和攔截響應(yīng)

    方法不同

    Servlet 只能接收請求和處理響應(yīng)

    Filter 可以接收請求和處理響應(yīng), 還可以攔截請求

    生命周期不同

    Servlet:第一次請求訪問的時候, 創(chuàng)建對象

    Filter:web 應(yīng)用加載的時候, 創(chuàng)建對象

    訪問的優(yōu)先級

    Filter 訪問優(yōu)先于 Servlet

    悲觀鎖和樂觀鎖

    CAS

    Java對象頭存放什么內(nèi)容

    Volatile 關(guān)鍵字以及底層實現(xiàn)

    線程池,線程池的作用

    AQS

    談?wù)凥ashSet的存儲原理

    HashSet與HashMap非常類似,最明顯的區(qū)別就是HashSet是屬于單列集合,HashMap為雙列集合。

    翻看HashSet源碼,可以發(fā)現(xiàn)HashSet底層使用了HashMap

    public HashSet() { map = new HashMap<>(); }

    HashSet在調(diào)用add(E e)方法時,會將傳入的對象作為key存入到HashMap中,統(tǒng)一以PRESENT作為假的value。

    public boolean add(E e) { return map.put(e, PRESENT)==null; }

    所以HashSet是以哈希表存儲的,目的是為了解決唯一性的問題。

    哈希表原理

    在JKD1.7以前,哈希表使用數(shù)組+鏈表的結(jié)構(gòu)完成的

    在JDK1.8后,哈希表使用數(shù)組+鏈表的結(jié)構(gòu),但是當(dāng)鏈表的長度>8時就會改用紅黑樹

    哈希存儲確保唯一性過程

    主要用到兩個方法,第一個就是Object的hashCode()方法,第二個就是使用了equals()方法進行內(nèi)容上的比對。

    首先第一步會對需要存入的對象進行哈希運算,并且與數(shù)組的長度-1進行位運算,從而得到該對象在數(shù)組存儲的位置。

    當(dāng)發(fā)生哈希沖突時,此時就會進行進一步的比較,通過調(diào)用equals方法來比較內(nèi)容,如果是相同的的內(nèi)容則不會繼續(xù)存儲,如果是不同的的內(nèi)容,此時就會以鏈表的形式繼續(xù)存儲。

    JDK1.8時做了優(yōu)化,當(dāng)鏈表的長度大于8時,就會將鏈表轉(zhuǎn)換為紅黑樹。

    談?wù)凩inkedHashMap和HashMap的區(qū)別(重點)

    共同點:二者都是屬于Map

    HashMap使用了哈希表的存儲形式:使用數(shù)組+鏈表的結(jié)構(gòu)

    HashMap的默認初始化大小為16,最大的裝載因子默認為0.75,當(dāng)HashMap的元素個數(shù)達到總?cè)萘康?.75時,就會在原先的基礎(chǔ)上擴容兩倍

    當(dāng)鏈表的長度大于8,且數(shù)組的容量大于64時就會將鏈表轉(zhuǎn)化為紅黑樹。

    LinkedHashMap與HashMap的主要不同就在于LinkedHashMap使用了鏈表+哈希表(散列表)的結(jié)構(gòu)。

    談?wù)凜oncurrentHashMap,HashMap,Hashtable的區(qū)別

    • Hashtable是線程安全的類,但是效率低
    • HashMap是線程不安全的類,效率高
    • Hashtable的key|value是不允許NULL,HashMap允許key|value為NUll值
    • Hashtable的父類為Dictionary,HashMap的父類為AbstractMap,但是它們都實現(xiàn)了Map接口

    ConcurrentHashMap在線程安全和效率上是一個折中的選擇,它屬于并發(fā)包java.util.concurrent下的一個類

    ConcurrentHashMap是線程安全的類,它能夠兼顧效率的原因是在于它把數(shù)據(jù)分段,執(zhí)行分段鎖,需要改哪部分就給哪部分上鎖,將范圍變小,從而提高效率。

    ConcurrentHashMap優(yōu)化

    JDK1.7采用分段鎖的方式,而JDK1.8采用CAS和synchronized的組合模式

    ArrayList vs Vector vs CopyOnWriteArrayList

    ArrayList 和Vector的區(qū)別:

    ArrayList :是線程不安全的類

    Vector:和ArrayList 基本類似,但是在每個方法都使用了synchronized,因此是線程安全的。

    在List集合中除了Vector是線程安全的,此外還有java.util.concurrent 包下的CopyOnWriteArrayList

    CopyOnWriteArrayList是線程安全的類,與ArrayList 基本類似。其中所有可變操作( add , set ,等等)通過對底層數(shù)組的最新副本實現(xiàn)。

    • 也就是說CopyOnWriteArrayList是讀寫分離的機制,在讀的時候不加鎖。

    • 每次數(shù)組操作,都會把數(shù)組拷貝一份出來,在新數(shù)組上進行操作,操作成功之后再賦值回
      去。

    開發(fā)一個自己的棧,你會怎么寫?

    • 棧(stack)在數(shù)據(jù)結(jié)構(gòu)中是屬于順序表的范疇,主要特點為先進后出(First in last Out)

    • 隊列(Queue)在數(shù)據(jù)結(jié)構(gòu)中是屬于順序表的范疇,主要特點為先進先出(First in First Out)

    棧的底層還是采用數(shù)組的形式,但是存和取要實現(xiàn)先進后出的特點

    棧主要有兩個方法,一個是push(E item)方法,另一個是E peek(),一個存,一個取。

    在Java中哪些情況使用了棧?

    如JVM當(dāng)中就使用了棧

    補充:集合知識小結(jié)

    Java集合中主要有兩大體系,分別為Collection和Map

    主要區(qū)別在于Collection是單列集合,Map是雙列集合。

    Collection主要有List和Set兩大類:

    • List下的集合主要有ArrayList(數(shù)組,線程不安全)、LinkList(鏈表,線程不安全)、Vector(數(shù)組,線程安全)、CopyOnWriteArrayList(數(shù)組,線程安全)
    • Set主要有HashSet(底層哈希)和LinkedHashSet(底層哈希+鏈表),LinkedHashSet使用鏈表可以實現(xiàn)排序(能排序,但不是有序。)
    • List是有序的,Set是無序的

    Map是雙列集合:

    • 主要分為HashMap(底層哈希,線程不安全)、HashTable(哈希,線程安全)
    • ConcurrentHashMap是一個效率和安全折中的選擇,既保證了線程安全,也兼顧了效率。它能夠兼顧效率的原因是在于它把數(shù)據(jù)分段,執(zhí)行分段鎖,需要改哪部分就給哪部分上鎖,將范圍變小,從而提高效率
    • 哈希在JDK1.8之后的優(yōu)化在于當(dāng)鏈表的長度大于8時,會將數(shù)組+鏈表的結(jié)構(gòu)轉(zhuǎn)化為數(shù)組+紅黑樹的結(jié)構(gòu)。
    • LinkedHashMap是Map的子類,使用了鏈表+哈希的數(shù)據(jù)結(jié)構(gòu),能夠記錄插入的順序。
    • HashMap的key|value可以為空,HashTable的key|value都不能為空。
    • HashMap的父類是AbstractMap,HashTable的父類是Dictionary,但是它們都實現(xiàn)了Map接口。

    談?wù)処O流的分類及選擇

    I指的是In,O指的是Out,即輸入輸出的意思。

    此處輸入輸出,是站在程序的角度來理解的:

    • 從程序中將文件信息寫入到本地,就是輸出-Out
    • 將文件從本地讀到程序中,就是輸入-In

    主要涵蓋四個流:InputString、OutPutString、Reader、Writer

    InputString和OutPutString為字節(jié)流,可以輸入輸出任何格式的文件。

    Reader和Writer為字符流,可以輸入輸出字符內(nèi)容的文本。

    serialVersionUID的作用是什么

    當(dāng)執(zhí)行序列化時,我們寫對象到磁盤中,會根據(jù)當(dāng)前這個類的結(jié)構(gòu)生成一個版本號ID

    當(dāng)反序列化時,程序會比較磁盤中的序列化版本號ID跟當(dāng)前的類結(jié)構(gòu)生成的版本號ID是否一致,如果一致則反序列化成功,否則,反序列化失敗

    加上版本號,有助于當(dāng)我們的類結(jié)構(gòu)發(fā)生了變化,依然可以之前已經(jīng)序列化的對象反序列化成功

    請描述下Java的異常體系

    Java中的異常體系都繼承了Throwable,因此常見的Error和Exception都是它的子類。

    按照異常類型可以劃分:

    • Error:程序中不可處理的重大錯誤,常見的有堆內(nèi)存溢出( OutOfMemoryError,在內(nèi)存中創(chuàng)建的對象過多 )、棧內(nèi)存溢出(StackOverFlowError,如遞歸次數(shù)過多)
    • Exception,也稱為異常,指程序可以捕獲處理的的異常。

    Exception下又含有運行時異常(RuntimeException)、編譯異常(IoException)

    RuntimeException:也稱為邏輯異常,常見的有NullPointerException、ArrayindexOutBoundsException等。

    IoException:在編譯時就會提示的異常,當(dāng)出現(xiàn)該異常時就要對該異常進行處理,否則就會編譯不通過。

    根據(jù)可查(checked Exception)和不可查異常(unchecked Exception)分類:

    • checked Exception:除了RuntimeException外的所有Exception都屬于可查異常,當(dāng)程序編譯時發(fā)生該異常時,就必須處理,否則編譯不通過。

    • unchecked Exception: RuntimeException和Error屬于不可查異常,沒有try、catch編譯時仍然可以通過

    羅列常見的5個運行時異常和非運行時異常

    運行時異常:

    NullPointerException

    ArrayIndexOutBoundsException

    ArithmeticException (算術(shù)異常,如1/0)

    IllegaArguementException (參數(shù)異常)

    NumberFormatException(數(shù)字格式異常)

    非運行時異常

    IOException 表示發(fā)生某種類型的I / O異常。 此類是由失敗或中斷的I / O操作產(chǎn)生的一般異常類。

    SQLException 提供有關(guān)數(shù)據(jù)庫訪問錯誤或其他錯誤的信息的異常

    FileNotFoundException 指示嘗試打開由指定路徑名表示的文件失敗。

    NoSuchFileException 當(dāng)嘗試訪問不存在的文件時拋出檢查的異常。

    NoSuchMethodException 當(dāng)無法找到特定方法時拋出

    throw跟throws的區(qū)別

    throw作用在代碼塊內(nèi),throws作用在方法上。

    ---------throws--------------public void test01() throws Exception{ //代碼塊}----------throw---------------public void test02(){ try{ //代碼塊 }catch(Exception){ //代碼塊 throw new RuntimeException("發(fā)生了異常"); }}

    一道關(guān)于try catch finally返回值的問題

    public int demo() {try {int a = 5/0;return 1;}catch (Exception e){return 2;}finally {return 3;}}

    結(jié)果為3,finally的優(yōu)先級大于catch

    創(chuàng)建線程的方式

    創(chuàng)建線程有四種方式:

    繼承Thread 實現(xiàn)Runable接口 實現(xiàn)Callable接口(可以獲取線程執(zhí)行之后的返回值) 從線程池中獲取

    方式一:繼承Thread類

    public class Demo01 {/*** 繼承Thread的方式*/@Testpublic void test01(){Demo demo = new Demo();demo.start();} } //定義一個類,繼承Thread,重寫run方法 class Demo extends Thread{@Overridepublic void run() {System.out.println("線程創(chuàng)建了:"+Thread.currentThread().getName());} }

    方式二:實現(xiàn)Runable接口

    //使用lambda的形式 /** * 實現(xiàn) Runable 接口 */ @Test public void test02(){ new Thread(() -> System.out.println("線程創(chuàng)建了:"+Thread.currentThread().getName())).start(); }-----------------//使用匿名內(nèi)部類 @Testpublic void test03(){ new Thread(new Runnable() { @Override public void run() { System.out.println("線程創(chuàng)建了:"+Thread.currentThread().getName()); } }).start();}

    方式三:實現(xiàn)Callable接口(可以獲取線程執(zhí)行之后的返回值)

    //繼承Callable接口 class Demo2 implements Callable<String>{ @Override public String call() throws Exception { System.out.println("多線程方法執(zhí)行了"); return "9999"; }} ---------調(diào)用測試方法-----------@Test public void test04(){ FutureTask futureTask = new FutureTask(new Demo2()); new Thread(futureTask).start(); }

    run方法和start()的區(qū)別

    • run方法是Runable接口中的一個抽象方法,start是Thread中的方法
    • run是線程需要執(zhí)行的代碼,start是將Thread線程啟動起來,會開辟新線程。
    • 通過調(diào)用start方法,會開辟新線程去執(zhí)行run方法;直接調(diào)用run方法是不會開啟新的線程的。

    面試提問:選擇Thread還是Runable?二者什么區(qū)別

  • 適合多個相同程序代碼的線程去處理同一個資源(多線程內(nèi)的數(shù)據(jù)共享)
  • 避免java特性中的單根繼承限制
  • 增加程序健壯性,數(shù)據(jù)被共享時,仍然可以保持代碼和數(shù)據(jù)的分離和獨立
  • 更能體現(xiàn)java面向?qū)ο蟮脑O(shè)計特點
  • 一個普通main方法的執(zhí)行,是單線程模式還是多線程模式?為什么

    多線程模式。

    除了Main方法的線程外,還有垃圾回收線程GC。

    請描述線程的生命周期

    線程的生命周期:

    • 新建狀態(tài) (New): 線程對象對創(chuàng)建后,即進入了新建狀態(tài),如:Thread t = new MyThread();
    • 就緒狀態(tài)(Runnable):當(dāng)線程對象調(diào)用了start方法時,就處于就緒狀態(tài)
    • 運行狀態(tài) (Running): 線程處于就緒狀態(tài),且得到CPU時間片時,CPU就會執(zhí)行該線程任務(wù),此時就為運行狀態(tài)
    • 阻塞狀態(tài)(Blocked):運行狀態(tài)的線程,調(diào)用sleep、wait方法,或未得到synchronized鎖時,就會進入阻塞狀態(tài)
    • 終止狀態(tài) (Terminated): 當(dāng)線程任務(wù)執(zhí)行完時,就進入了終止狀態(tài)。

    調(diào)用wait方法,需要使用notify()或notifyAll()來喚醒線程

    notify:會隨機喚醒一個線程

    notifyAll:喚醒所有的線程

    談?wù)勀銓hreadLocal的理解

    ThreadLocal這個類提供線程局部變量。 這些變量與其正常的對應(yīng)方式不同,因為訪問一個的每個線程(通過其get或set方法)都有自己獨立初始化的變量副本。 ThreadLocal實例通常是希望將狀態(tài)與線程關(guān)聯(lián)的類中的私有靜態(tài)字段(例如,用戶ID或事務(wù)ID)。

    ThreadLocal能夠為每個線程創(chuàng)建一個獨立的副本,從而避免了多線程環(huán)境下操作共享資源的安全問題

    public class ThreadLocalTest { //定義一個成員變量 static ThreadLocal<Long> threadLocal = new ThreadLocal<>(); /** * 定義一個方法,開辟兩個線程,打印其值觀察是否是同一個線程 * 如果打印的線程是不同的值,就表面threadLocal會為每個線程創(chuàng)建獨立副本 **/ public static void main(String[] args) throws Exception { Task task = new Task(); new Thread(task).start(); Thread.sleep(10);//休眠一下,防止太快看不出效果 new Thread(task).start(); } static class Task implements Runnable{ @Override public void run() { //獲取一下當(dāng)前的threadLocal Long local = threadLocal.get(); if(local == null){ //如果local為Null就手動賦值 threadLocal.set(System.currentTimeMillis()); //打印查看結(jié)果 System.out.println("當(dāng)前的local:"+threadLocal.get()); } } }}

    此時可以發(fā)現(xiàn)打印出來的結(jié)果是不一樣的。

    ThreadLocal最主要的兩個方法get和set,通過分析:

    可以看到,無論是get還是set,都有最核心的兩句話

    //獲取當(dāng)前線程Thread t = Thread.currentThread();//從ThreadMap中獲取當(dāng)前線程的mapThreadLocalMap map = getMap(t);

    也就是說,無論是存還是取使用ThreadLocal操作的都是當(dāng)前線程的對象,這也就說明了ThreadLocal使同一變量在每一個線程中有各自的副本,只有指定的線程能拿到特點的數(shù)據(jù)。

    案例說明:

    Java程序?qū)?shù)據(jù)庫的連接操作都是基于JDBC來完成的,在開發(fā)中根據(jù)不同的功能分為了web層、service層,dao層。

    其中對于事務(wù)的控制是放在service層中解決的。

    public class UserService { private UserDao userDao = new UserDao(); private LogDao logDao = new LogDao(); public void add(){ userDao.add(); logDao.add(); } }

    如此處service調(diào)用了兩個dao,那么兩個dao是如何實現(xiàn)事務(wù)的控制的?

    在JDBC中,如要實現(xiàn)事務(wù),就必須要保證兩個dao是有相同的Connection連接對象,因此只需要保證Connection是相同的即可。

    因為整個UserService都是同一個線程去調(diào)用userDao和logDao,因此就可以使用ThreadLocal來解決這個問題

    /** * 使用 ThreadLocal 來存儲Connection對象 * 因此service是使用同一個線程來調(diào)用dao的 * 因此可以使用ThreadLocal訪問當(dāng)前線程的特有數(shù)據(jù) */ public class ConnectionUtils { private ThreadLocal<Connection> threadLocal = new ThreadLocal<>(); public static Connection getConnection(){ Connection connection = threadLocal.get(); if(connection == null){ connection = new Connection(); threadLocal.set(connection); } return connection; }}

    通過ThreadLocal會為每個線程創(chuàng)造一個副本的特點, 因此可以將Connection存儲到ThreadLocal對象中,只要是同一個線程訪問的,就可以拿到相同的Connection對象。

    談?wù)凙Jax的工作原理

    Ajax 的全稱是Asynchronous JavaScript and XML(異步的JavaScript 和 XML),ajax中最后的x指的是xml,早起都是使用xml作為數(shù)據(jù)交互,現(xiàn)在json更為輕量,基本都是使用json數(shù)據(jù)。

    在前后端不分離的時代,沒有引入Ajax時,客戶端發(fā)送的請求流程是如下這樣的:

    客戶端發(fā)起請求,服務(wù)器將整個HTML+CSS數(shù)據(jù)都響應(yīng)給客戶端

    引入Ajax的工作模式是這樣的:

    相比較傳統(tǒng)模式,引入了一個AJax引擎,通過使用XMLHttpRequest發(fā)送異步請求到服務(wù)器,服務(wù)器將數(shù)據(jù)響應(yīng)到AJAX引擎,利用回調(diào)函數(shù)進行數(shù)據(jù)的渲染,響應(yīng)HTML+CSS數(shù)據(jù),從而實現(xiàn)異步刷新。

    談?wù)凷ervlet的生命周期

    Servlet的生命周期

    Servlet創(chuàng)建 -> 初始化 -> 調(diào)用service方法 ->調(diào)用doGet/doPost方法 -> 銷毀

    Servlet是一種單例類型的,從創(chuàng)建到銷毀只會被執(zhí)行一次

    創(chuàng)建 - > 執(zhí)行一次

    初始化 ->執(zhí)行一次

    銷毀 -> 執(zhí)行一次

    其中,Servlet默認是在第一次訪問時才被創(chuàng)建,也可以通過配置的形式讓servlet在容器啟動時就創(chuàng)建。

    Servlet不是線程安全的類,在并發(fā)條件下會有線程不安全的情況,因此因避免操作共享數(shù)據(jù)。

    描述Session跟Cookie的區(qū)別(重要)

    • Session存儲在服務(wù)器中,Cookie存儲在瀏覽器(客戶端)中
    • Session存儲的對象為鍵值對形式,Cookie儲存的數(shù)據(jù)格式為字符串(可轉(zhuǎn)為JSON)
    • Session生命默認為30分鐘, Cookie 默認隨著瀏覽器的關(guān)閉而關(guān)閉,也可以通過 設(shè)置有效期來控制Cookie的生命。

    理解

    在日常過程中,小明問小軍:“你喜歡吃什么” ,小軍回答:“我喜歡吃四飯燒鴨飯”,那么這個過程
    其實就是一問一答的過程,或者換句話說,就是一次會話(Session)

    當(dāng)客戶端發(fā)起請求,瀏覽器就會響應(yīng)結(jié)果,那么我們可以說是一次請求,一次響應(yīng),整個過程就是
    一次通信會話。

    由于HTTP通信協(xié)議是無狀態(tài)的,服務(wù)器無法直接鑒別當(dāng)前客戶信息,我們就需要一種技術(shù),讓服
    務(wù)器能夠記住當(dāng)前用戶。因為我們不可能登錄A頁面后,需要訪問B頁面時又重新登錄,訪問C頁面的時
    候又重新登錄。

    我們需要的效果是,當(dāng)我登錄了當(dāng)前的網(wǎng)站,隨后用戶的相關(guān)信息都能被記錄,服務(wù)器能夠識別當(dāng)
    前用戶信息,登錄了A頁面后,無論訪問B頁面還是C頁面,服務(wù)器都能記住我,那么就需要這種會話技
    術(shù)Session了。

    所以,當(dāng)我關(guān)閉瀏覽器時,服務(wù)器就會認為你跟它的會話已經(jīng)結(jié)束,那么存儲在Session的用戶信
    息也會隨之而刪除,這也是為什么關(guān)閉瀏覽器下次就需要重新登錄的原因了。

    Cookie在百科是的為:“儲存在用戶本地終端上的數(shù)據(jù)”,也就是說,Cookie是能信息保存到當(dāng)前
    的客戶端本地(當(dāng)然也包括用戶信息了),而Session存儲的用戶信息保存到服務(wù)器上,這是二者的不同。

    當(dāng)保存到本地時,即便關(guān)閉瀏覽器,當(dāng)我下次打開網(wǎng)站,瀏覽器就能在請求服務(wù)器的同時將Cookie
    一起發(fā)送給服務(wù)器,從而讓服務(wù)器能夠正常鑒別用戶信息,所以有時候也可以做長時間的登錄這個功
    能。

    由于Cookie是存儲在客戶端本地的,所以就會有被攻擊和篡改的可能,因此這也讓Cookie存儲用
    戶信息變得不安全。比如有可能會遭到CSRF的攻擊,這里沒有詳細的解釋

    補 Get請求與Post請求的區(qū)別

    經(jīng)常會聽到,你的這個請求到底是get的請求呢還是post請求呢?

    從簡單的來講二者區(qū)別:

    • post的請求比get請求更安全,因為get的請求直接把參數(shù)暴露到URL上。就比如做登錄用post而不
      是get,get會使你的密碼暴露出去,顯然更加不安全。
    • get的請求參數(shù)往往在url中,而post的參數(shù)是放在請求體當(dāng)中的。如果不了解請求頭、請求體這些
      知識,可以去了解一下HTTP協(xié)議。
    • GET在瀏覽器回退時是無害的,而POST會再次提交請求。
      主要是這些,百度上還有更詳細的,就看你的需求了

    轉(zhuǎn)發(fā)和重定向的區(qū)別

    轉(zhuǎn)發(fā):是指發(fā)生在服務(wù)器內(nèi)部的跳轉(zhuǎn),此時只有一次請求

    重定向:指發(fā)生客戶端之間的跳轉(zhuǎn),有兩次請求。

    區(qū)別:

    • 轉(zhuǎn)發(fā)請求一次,重定向請求多次
    • 轉(zhuǎn)發(fā)發(fā)生在服務(wù)器內(nèi)部之間,重定向發(fā)生在客戶端

    重定向?qū)嵗?#xff1a;

    如登錄時,需要發(fā)起一個 POST請求,登錄成功時就會返回狀態(tài)碼302,然后重定向到首頁(用戶中心)

    Iterator和ListIterator的區(qū)別?

    Iterator [?t?’re?t?] :可以遍歷Set和List,而ListIterator只能遍歷List

    Iterator只能單向遍歷,而ListIterator可以雙向遍歷

    ListIterator繼承與Iterator接口

    并發(fā)和并行的區(qū)別

    并發(fā)和并行是兩個不同的概念

    • 并發(fā)指的是某一個處理器同時處理多個請求,如同一個CPU處理多個任務(wù)時,通過時間片的方式快速的切換完成多個任務(wù)。
    • 并行是指多個處理器去同時處理多個請求,此時好比有多個CPU去同時處理多個任務(wù),使用多核處理器,處理多任務(wù)的能力自然而然強。

    什么是序列化?

    序列化是為了保持對象在內(nèi)存中的狀態(tài),并且可以把保存的對象狀態(tài)再讀出來。

    什么時候需要用到j(luò)ava序列化?

    1,需要將內(nèi)存的對象狀態(tài)保存到文件中

    2,需要通過socket通信進行對象傳輸時

    3,我們將系統(tǒng)拆分成多個服務(wù)之后,服務(wù)之間傳輸對象,需要序列化

    說說synchronized底層原理

    這個我們要分情況來分析:

    1,JDK1.6之前

    synchronized是由一對monitor-enter和monitor-exit指令實現(xiàn)的。

    這對指令的實現(xiàn)是依靠操作系統(tǒng)內(nèi)部的互斥鎖來實現(xiàn)的,期間會涉及到用戶態(tài)到內(nèi)存態(tài)的切換,所以這個操作是一個重量級的操作,性能較低。

    2,JDK1.6之后

    JVM對synchronized進行了優(yōu)化,改了三個經(jīng)歷的過程

    偏向鎖-》輕量級鎖-》重量級鎖

    偏向鎖:

    在鎖對象保存一個thread-id字段,剛開始初始化為空,當(dāng)?shù)谝淮尉€程訪問時,則將thread-id設(shè)置為當(dāng)前線程id,此時,我們稱為持有偏向鎖。

    當(dāng)再次進入時,就會判斷當(dāng)前線程id與thread-id是否一致

    如果一致,則直接使用此對象

    如果不一致,則升級為輕量級鎖,通過自旋鎖循環(huán)一定次數(shù)來獲取鎖

    如果執(zhí)行了一定次數(shù)之后,還是沒能獲取鎖,則會升級為重量級鎖。

    鎖升級是為了降低性能的消耗。s

    synchronized和volatile的區(qū)別

    1,作用的位置不同

    synchronized是修飾方法,代碼塊

    volatile**[?v?l?ta?l]** 是修飾變量

    2,作用不同

    synchronized,可以保證變量修改的可見性及原子性,可能會造成線程的阻塞

    volatile僅能實現(xiàn)變量修改的可見性,但無法保證原子性,不會造成線程的阻塞

    volatile的實現(xiàn):

    volatile是一個輕量級的線程同步機制。它的特性之一,是保證了變量在線程之間的可見性。

    所謂的可見性是指當(dāng)一個線程修改了變量的值之后,其他線程可以感知到該變化。

    為什么會有可見性問題?

    是因為由于硬件速度的不同,CPU的速度要明顯快于主內(nèi)存。

    所以為了解決速度不匹配的問題,在CPU到主內(nèi)存之間就會有多級的緩存。

    那么這個時候就會發(fā)生,一個線程修改了數(shù)據(jù),數(shù)據(jù)還沒有及時刷到主內(nèi)存,那么其他線程讀取到的數(shù)據(jù)就依然還是舊的,這就是可見性問題發(fā)生的根源。

    通過給變量設(shè)置volatile關(guān)鍵字修飾,可以保證變量在線程修改完之后,會刷新到共享內(nèi)存,這樣其他線程就可以讀取到最新的內(nèi)容

    volatile保證了在多個線程之間是可見的,但不能保證原子性操作。

    volatile vs synchronized

    synchronized也是保證了線程的可見性,同時也具備了多線程之間的互斥性

    3,如何使用volatile

    直接修飾變量即可

    private volatile int count;

    4,volatile底層實現(xiàn)原理

    當(dāng)變量被聲明為volatile后,線程每次都會都從主內(nèi)存去讀取,而不是讀取自己的工作內(nèi)存,這樣就實現(xiàn)了線程之間的可見性

    synchronized和lock的區(qū)別

    1,作用的位置不同

    synchronized可以給方法,代碼塊加鎖

    lock只能給代碼塊加鎖

    2,鎖的獲取鎖和釋放機制不同

    synchronized無需手動獲取鎖和釋放鎖,發(fā)生異常會自動解鎖,不會出現(xiàn)死鎖。

    lock需要自己加鎖和釋放鎖,如lock()和unlock(),如果忘記使用unlock(),則會出現(xiàn)死鎖,

    所以,一般我們會在finally里面使用unlock().

    補充:

    //明確采用人工的方式來上鎖

    lock.lock();

    //明確采用手工的方式來釋放鎖

    lock.unlock();

    synchronized修飾成員方法時,默認的鎖對象,就是當(dāng)前對象

    synchronized修飾靜態(tài)方法時,默認的鎖對象,當(dāng)前類的class對象,比如User.class

    synchronized修飾代碼塊時,可以自己來設(shè)置鎖對象,比如

    synchronized(this){

    //線程進入,就自動獲取到鎖

    //線程執(zhí)行結(jié)束,自動釋放鎖

    }

    什么是死鎖?如何防止死鎖?

    如何防止死鎖?

    減少同步代碼塊嵌套操作

    降低鎖的使用粒度,不要幾個功能共用一把鎖

    盡量采用tryLock(timeout)的方法,可以設(shè)置超時時間,這樣超時之后,就可以主動退出,防止死鎖(關(guān)鍵)

    什么是反射?可以解決什么問題?

    反射是指程序在運行狀態(tài)中,

    1,可以對任意一個類,都能夠獲取到這個類的所有屬性和方法。

    2,對于任意一個對象,都可以調(diào)用它的任意一個方法和屬性

    反射是一種能力

    一種在程序運行時,動態(tài)獲取當(dāng)前類對象的所有屬性和方法的能力,可以動態(tài)執(zhí)行方法,給屬性賦值等操作的能力

    Class代表的就是所有的字節(jié)碼對象的抽象,類

    反射,讓我們的java程序具備動態(tài)性

    這種動態(tài)獲取類信息及調(diào)用對象方法的功能稱為反射

    這種能力帶來很多的好處,在我們的許多框架的背后實現(xiàn)上,都采用了反射的機制來實現(xiàn)動態(tài)效果。

    框架是提供一種編程的約定

    比如@Autowrie 就能實現(xiàn)自動注入

    @Autowrie

    private IUserService userService;

    注解的解析程序,來掃描當(dāng)前的包下面有哪些屬性加了這個注解,一旦有這個注解,就要去容器里面獲取對應(yīng)的類型的實現(xiàn),然后給這個屬性賦值。

    什么是悲觀鎖,什么是樂觀鎖?

    1,悲觀鎖是利用數(shù)據(jù)庫本身的鎖機制來實現(xiàn),會鎖記錄。

    實現(xiàn)的方式為:select * from t_table where id = 1 for update

    2,樂觀鎖是一種不鎖記錄的實現(xiàn)方式,采用CAS模式,采用version字段來作為判斷依據(jù)。

    每次對數(shù)據(jù)的更新操作,都會對version+1,這樣提交更新操作時,如果version的值已被更改,則更新失敗。

    3,樂觀鎖的實現(xiàn)為什么要選擇version字段,如果選擇其他字段,比如業(yè)務(wù)字段store(庫存),那么可能會出現(xiàn)所謂的ABA問題

    數(shù)據(jù)庫說明

    數(shù)據(jù)庫的完整知識可以參考我的這篇文章,這是我總結(jié)的一個比較完整的知識點全集,字數(shù)在1W+

    https://blog.csdn.net/wq2323/article/details/111768680

    談?wù)剶?shù)據(jù)庫設(shè)計的三大范式及反范式

    數(shù)據(jù)庫的三大范式

    第一范式:列不可分
    第二范式:要有主鍵
    第三范式:不可存在傳遞依賴
    比如商品表里面關(guān)聯(lián)商品類別表,那么只需要一個關(guān)聯(lián)字段product_type_id即可,其他字段信息可以通過表關(guān)聯(lián)查詢即可得到
    如果商品表還存在一個商品類別名稱字段,如product_type_name,那就屬于存在傳遞依賴的情況,第三范式主要是從空間的角度來考慮,避免產(chǎn)生冗余信息,浪費磁盤空間

    反范式設(shè)計:(第三范式)

    為什么會有反范式設(shè)計?
    原因一:提高查詢效率(讀多寫少)
    比如上述的描述中,顯示商品信息時,經(jīng)常需要伴隨商品類別信息的展示,
    所以這個時候,為了提高查詢效率,可以通過冗余一個商品名稱字段,這個可以將原先的表關(guān)聯(lián)查詢轉(zhuǎn)換為單表查詢

    原因二:保存歷史快照信息
    比如訂單表,里面需要包含收貨人的各項信息,如姓名,電話,地址等等,這些都屬于歷史快照,需要冗余保存起來,
    不能通過保存用戶地址ID去關(guān)聯(lián)查詢,因為用戶的收貨人信息可能會在后期發(fā)生變更

    左連接,右連接,內(nèi)連接,如何編寫SQL,他們的區(qū)別是什么?

    左連接:以左表為主

    select a.,b. from a left join b on a.b_id = b.id;

    右連接:以右表為主

    select a.,b. from a right join b on a.b_id = b.id;

    內(nèi)連接:只列出兩張表關(guān)聯(lián)查詢符合條件的記錄

    select a.,b. from a inner join b on a.b_id = b.id;

    如何解決SQL注入?

    SQL注入,是指通過字符串拼接的方式構(gòu)成了一種特殊的查詢語句

    比如:select * from t_user where usename=’’ and password=’’
    ’ or 1=1 #
    select * from t_user where usename=’’ or 1=1 # ’ and password=’’

    解決方案

    采用預(yù)處理對象,采用PreparedStatement對象,而不是Statement對象
    可以解決SQL注入的問題
    另外也可以提高執(zhí)行效率,因為是預(yù)先編譯執(zhí)行
    SQL執(zhí)行過程(語法校驗->編譯->執(zhí)行)

    延伸

    MyBatis如何解決了SQL注入的問題?采用#
    MyBatis的#和KaTeX parse error: Expected 'EOF', got '#' at position 5: 的差異,#?可以解決SQL注入,而號不能解決

    JDBC如何實現(xiàn)對事務(wù)的控制及事務(wù)邊界

    JDBC對事務(wù)的操作是基于Connection來進行控制的,具體代碼如下:

    try { //開啟事務(wù) connection.setAutoCommit(false); //做業(yè)務(wù)操作 //doSomething(); //提交事務(wù) connection.commit();}catch(Exception e){ //回滾事務(wù) try { connection.rollback(); } catch (SQLException e1) { e1.printStackTrace(); }}

    但,注意,事務(wù)的邊界我們是放在業(yè)務(wù)層進行控制,因為業(yè)務(wù)層通常包含多個dao層的操作。

    談?wù)勈聞?wù)的特點

    原子性是基礎(chǔ),隔離性是手段,一致性 是約束條件,而持久性是我們的目的。

    簡稱,ACID

    原子性( Atomicity )、一致性( Consistency )、隔離性( Isolation )和持久性( Durability )

    原子性:

    事務(wù)是數(shù)據(jù)庫的邏輯工作單位,事務(wù)中包含的各操作要么都完成,要么都不完成
    (要么一起成功,要么一起失敗)

    一致性:

    事務(wù)一致性是指數(shù)據(jù)庫中的數(shù)據(jù)在事務(wù)操作前后都必須滿足業(yè)務(wù)規(guī)則約束。
    比如A轉(zhuǎn)賬給B,那么轉(zhuǎn)賬前后,AB的賬戶總金額應(yīng)該是一致的。

    隔離性:

    一個事務(wù)的執(zhí)行不能被其它事務(wù)干擾。即一個事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對其它并發(fā)事務(wù)是隔離的,并發(fā)執(zhí)行的各個事務(wù)之間不能互相干擾。
    (設(shè)置不同的隔離級別,互相干擾的程度會不同)

    持久性:

    事務(wù)一旦提交,結(jié)果便是永久性的。即使發(fā)生宕機,仍然可以依靠事務(wù)日志完成數(shù)據(jù)的持久化。

    日志包括回滾日志(undo)和重做日志(redo),當(dāng)我們通過事務(wù)修改數(shù)據(jù)時,首先會將數(shù)據(jù)庫變化的信息記錄到重做日志中,然后再對數(shù)據(jù)庫中的數(shù)據(jù)進行修改。這樣即使數(shù)據(jù)庫系統(tǒng)發(fā)生奔潰,我們還可以通過重做日志進行數(shù)據(jù)恢復(fù)。

    談?wù)勈聞?wù)的隔離級別

    有以下4個級別:

    l READ UNCOMMITTED 讀未提交,臟讀、不可重復(fù)讀、幻讀有可能發(fā)生。
    l READ COMMITTED 讀已提交,可避免臟讀的發(fā)生,但不可重復(fù)讀、幻讀有可能發(fā)生。
    l REPEATABLE READ 可重復(fù)讀,可避免臟讀、不可重復(fù)讀的發(fā)生,但幻讀有可能發(fā)生。
    l SERIALIZABLE 串行化,可避免臟讀、不可重復(fù)讀、幻讀的發(fā)生,但性能會影響比較大。

    特別說明:

    幻讀,是指在本地事務(wù)查詢數(shù)據(jù)時只能看到3條,但是當(dāng)執(zhí)行更新時,卻會更新4條,所以稱為幻讀

    InnoDB是如何支持事務(wù)的 ?

    通過日志的形式來確保事務(wù)。

    redo log 與 undo log 實現(xiàn)的。

    介紹一下MVCC

    多版本并發(fā)控制(Multi-Version Concurrency Control, MVCC)是 MySQL 的 InnoDB 存儲引擎實現(xiàn)隔離級別的一種具體方式,用于實現(xiàn)提交讀和可重復(fù)讀這兩種隔離級別。而未提交讀隔離級別總是讀取最新的數(shù)據(jù)行,要求很低,無需使用MVCC。可串行化隔離級別需要對所有讀取的行都加鎖,單純使用 MVCC 無法實現(xiàn)。

    索引如何避免全表掃描(索引失效)

    為了避免全表掃描,首先應(yīng)考慮在 where 及 order by 涉及的列上建立索引。

    列舉幾個比較常見的:

  • 應(yīng)盡量避免在 where 子句中對字段進行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進行全表掃描, 任何在 where 子句中使用 is null 或 is not null 的語句優(yōu)化器是不允許使用索引
  • 應(yīng)盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。使用LIKE操作時要確保不是以%或_開頭的,否則索引將失效進行全表掃描。
  • 應(yīng)盡量避免在 where 子句中使用 or 來連接條件,否則將導(dǎo)致引擎放棄使用索引而進行全表掃描
  • in 和 not in 也要慎用,否則會導(dǎo)致全表掃描,如select id from t where num in(1,2,3)將導(dǎo)致索引失效,如果量不多的話可以考慮使用BETWEEN
  • 索引并不是越多越好,索引固然可以提高相應(yīng)的 select 的效率,但同時也降低了 insert 及 update 的效率,因為insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數(shù)最好不要超5條索引。
  • 如果需要使用like ‘%關(guān)鍵字%’ 去模糊查詢,建議使用全文索引來提高效率,否則索引失效導(dǎo)致全文檢索。
  • 最左前綴

    最左前綴是針對聯(lián)合索引來說,例如三個字段組成的聯(lián)合索引,abc、ab、a=ac。使用 abc 會完全使用聯(lián)合索引的 abc三列,使用 ab 只會使用聯(lián)合索引中的兩列,使用 a 或者 ac 只會使用聯(lián)合索引中的 a 列。

    需要滿足兩個條件:需要查詢的列和組合索引的列順序一致 查詢不要跨列

    之所以會有最左原則,是因為聯(lián)合索引的 B+樹是按照第一個關(guān)鍵字進行索引排列的。

    查詢很慢怎么解決 ?

    1、 開啟慢查詢?nèi)罩?#xff0c;根據(jù)日志找到哪條 SQL 語句執(zhí)行的慢。要調(diào)用 set 將 slow_query_log 參數(shù)設(shè)置成 1,開啟這個慢查詢?nèi)罩尽?#xff08;日志分析工具 mysqldumpslow)

    2、 用 Explain 關(guān)鍵字分析這條 SQL 語句,查看是否建立了索引。如果沒有,就可以考慮建立索引。如果建立了索引,但是并沒有使用到,就分析它為什么沒有使用到索引。

    計算機網(wǎng)絡(luò)

    說說TCP和UDP的區(qū)別

    首先,兩者都是傳輸層的協(xié)議。其次,

    tcp提供可靠的傳輸協(xié)議,傳輸前需要建立連接,面向字節(jié)流,傳輸慢

    udp無法保證傳輸?shù)目煽啃?#xff0c;無需創(chuàng)建連接,以報文的方式傳輸,效率高

    TCP/IP協(xié)議基礎(chǔ)

    層次各層協(xié)議端口
    TCP 20FTP文件傳輸中的數(shù)據(jù)傳輸
    TCP 21FTP文件傳輸中的控制命令
    TCP 22SSH安全遠程登錄
    TCP 23Telnet[?telnet]遠程登錄
    TCP 25SMTP電子郵件傳輸
    TCP 80HTTPWWW服務(wù)
    TCP 110POP3郵件接收
    TCP 139NETBIOS SESSION SERVICESamba服務(wù)
    TCP/UDP 53DNS域名解析服務(wù)
    UDP 69TFTP簡單的文件傳輸

    計算機網(wǎng)絡(luò)層次

    思維導(dǎo)圖:

    1、鏈路層

    鏈路層有時也稱作數(shù)據(jù)鏈路層或網(wǎng)絡(luò)接口層,通常包括操作系統(tǒng)中的設(shè)備驅(qū)動程序和計算機中對應(yīng)的網(wǎng)絡(luò)接口卡。

    2、網(wǎng)絡(luò)層

    網(wǎng)絡(luò)層處理分組在網(wǎng)絡(luò)中的活動,例如分組的選路。在TCP/IP協(xié)議族中,網(wǎng)絡(luò)層協(xié)議包括ARP(Address Resolution Protocol,地址解析協(xié)議)、IP協(xié)議(Internet Protocol,網(wǎng)際協(xié)議)、ICMP協(xié)議(Internet Control Message Protocol,網(wǎng)際控制報文協(xié)議)和IGMP協(xié)議(Internet Group Management Protocol,網(wǎng)際組管理協(xié)議)。RARP(Reverse Address Resolution Protocol,逆地址解析協(xié)議)。

    3、傳輸層

    傳輸層主要為兩臺主機上的應(yīng)用程序提供端到端的通信。在TCP/IP協(xié)議族中,有兩個互不相同的傳輸協(xié)議:TCP(Transmission Control Protocol,傳輸控制協(xié)議)和UDP(User Datagram Protocol,用戶數(shù)據(jù)報協(xié)議)。

    4、應(yīng)用層

    應(yīng)用層負責(zé)處理特定的應(yīng)用程序細節(jié)。幾乎各種不同的TCP/IP實現(xiàn)都會提供下面這些通用的應(yīng)用程序:Telnet遠程登錄(23)、SMTP(25)、FTP(21/20)、HTTP(80)、POP3(110)DNS(53)

    SSL概述

    概述

    SSL (Secure Sockets Layer)由Netscape公司1996年開發(fā),其目的是在客戶端和服務(wù)器端之間建立安全通道,從而提高WEB數(shù)據(jù)傳輸?shù)陌踩浴?/p>

    目前主流瀏覽器都支持SSL

    SSL的作用

    • 保密性 SSL采用的對稱加密技術(shù)保證信息的機密性。
    • 完整性。通信的發(fā)送方通過散列函數(shù)產(chǎn)生消息驗證碼(MAC),接收方通過驗證MAC來保證信息的完整性。SSL 提供完整性校驗服務(wù),使所有經(jīng)過SSL協(xié)議處理的業(yè)務(wù)都能全部準確、無誤地到達目的地。
    • 身份認證(鑒別) SSL采用數(shù)字證書進行身份認證。
    • SSL協(xié)議在可靠的傳輸層協(xié)議(如:TCP)之上。SSL協(xié)議的優(yōu)勢在于它是與應(yīng)用層協(xié)議獨立無關(guān)的。

    即:保密性、完整性、身份認證,沒有不可否認性

    HTTP 和 HTTPS 的區(qū)別

    端口: HTTP 的 URL 由“http”起始且默認的端口是 80,而 HTTPS 的 URL 由“https”起始且默認端口是 443;

    安全性和資源消耗

    HTTP 協(xié)議運行在 TCP 之上,所有傳輸?shù)膬?nèi)容都是明文,客戶端和服務(wù)端都無法驗證對方的身份。

    HTTPS 是運行在 SSL/TLS 之上的 HTTP 協(xié)議, SSL/TLS 是運行在 TCP 之上。 所有傳輸?shù)膬?nèi)容都經(jīng)過加密,加密
    采用對稱加密,但對稱加密的密鑰用服務(wù)器方的證書進行了非對稱加密(采用對稱和非對稱兩種加密方式相結(jié)合
    的加密方式) 。所以說, HTTP 安全性沒有 HTTPS 高,但是 HTTPS 比 HTTP 耗費更多服務(wù)器資源。

    對稱密鑰加密:這種加密方式的加密算法是公開的,密鑰是保密的,加密和解密采用同一個密鑰,也就是任何人得到了
    密鑰就能進行加密和解密

    弊端:在進行通信時,也必須把密鑰發(fā)給對方,否則對方無法解密,而在把密鑰發(fā)給對方的過程中,就存在安全問題23
    非對稱密鑰加密:這種加密方式有兩把密鑰,一把公鑰,可以公開告訴任何人,一把私鑰,只能自己持有。
    弊端:使用公鑰對消息加密速度比較慢

    談?wù)勈裁词荰CP的三次握手,可不可以只握手兩次?

    談?wù)勈裁词荰CP的四次揮手?

    瀏覽器輸入 URL 并回車的過程以及相關(guān)協(xié)議,DNS 查詢過程

    JVM虛擬機

    JVM內(nèi)存區(qū)域是怎么劃分的?

    JVM內(nèi)存主要有三個部分劃分:線程私有的、線程共享的、直接內(nèi)存

    程序計數(shù)器

    程序計數(shù)器在內(nèi)存中分配了一塊較小的區(qū)域,它可以看作是當(dāng)前線程執(zhí)行行數(shù)的指示器。

    Java多線程的實現(xiàn)通常采用CPU時間片的方式進行快速切換,為了恢復(fù)CPU再次執(zhí)行該線程時的位置,就需要一個能夠記住該線程執(zhí)行行號的計數(shù)器。

    虛擬機棧(Stack):

    虛擬機棧的生命周期和線程的生命周期是相同的,當(dāng)程序每調(diào)用一個方法時,就會產(chǎn)生一個棧幀;虛擬機棧主要存儲的信息有:局部變量表、方法出口等,只有當(dāng)方法調(diào)用完成時,壓入虛擬機的棧幀才會從棧中退出。

    局部變量表:主要存放的是在編譯時已知的基本類型變量和引用類型變量的引用地址,在內(nèi)部存儲是以局部變量槽(Slot)來表示的。

    本地方法棧(Native Stack)

    與虛擬機棧類似,區(qū)別在于本地方法棧執(zhí)行的是被 native修飾的本地方法,而虛擬機棧為普通的Java程序服務(wù)。

    堆(heap)

    Java的堆內(nèi)存主要存放的是對象實例和數(shù)組,是虛擬機內(nèi)存區(qū)域中最大的一塊區(qū)域,是線程共享的區(qū)域,也是垃圾回收器進行垃圾回收的一塊重要區(qū)域。

    根據(jù)GC的角度來劃分的話,堆內(nèi)存又劃分為新生代和老年代。

    新生代分為eden區(qū)、from survivor、to survivor區(qū)

    方法區(qū)

    JVM中的方法區(qū)并不是一個實在的物理概念,方法區(qū)它用于存儲已經(jīng)被虛擬機加載的類型信息、常量、靜態(tài)變量等數(shù)據(jù),但是方法區(qū)僅僅是一個邏輯上的概念。這就好比接口與實現(xiàn)類的關(guān)系一樣,方法區(qū)僅僅是一個接口,一種規(guī)范,而永久代便是它的實現(xiàn)類。

    在JDK1.6時代,使用永久代來實現(xiàn)方法區(qū)

    到了JDK1.8的時候,摒棄了永久代的概念,采用了元空間的概念,即使用計算機的物理內(nèi)存作為元空間的內(nèi)存,同時將永久代的字符串常量池移出到堆內(nèi)存中。

    JDK1.6時期的方法區(qū)(永久代)

    JDK8時期摒棄永久代的概念,使用元空間實現(xiàn)方法區(qū),同時將常量池里的字符串池也挪到了堆中。

    常量池與運行時常量池

    常量池是一張表,JVM虛擬機根據(jù)常量表來找到需要訪問的類名、方法名、變量等信息。

    當(dāng)程序運行時,就會把常量池的信息挪到運行時常量池,此時JVM虛擬機訪問的類名、方法名、變量等信息的地址就會變成真實的物理地址,因此把該常量池稱為運行時常量池。

    StringTable

    又稱字符串常量池,屬于常量池的一部分(jdk1.6時期,1.8時期存放在堆中)

    有以下特性:

    • 在常量池內(nèi)出現(xiàn)的字符串僅僅只是一個‘符號’,只有當(dāng)變量引用時才會變成一個字符串對象。
    • 字符串拼接時,實際上使用的是StringBuilder對象的append()方法

    如以下字符串 a/b,使用+號時實際上調(diào)用的是StringBuilder

    String a = "a"; String b = "b"; String c = "ab"; String ab = a+b; System.out.println(c == ab);//false

    實際上使用的是:

    new StringBuilder().append(a).append(b).toString();

    但是我們通過源碼發(fā)現(xiàn)

    @Override public String toString() { // Create a copy, don't share the array return new String(value, 0, count); }

    在StringBuilder內(nèi)部的toString()方法中,使用了new String()來得到字符串對象,這也就導(dǎo)致了c==ab為false的原因

    該原理是通過編譯期優(yōu)化得到的。

    intern

    new出來的字符串存放在堆中,而直接引用字符串的變量是引用常量池的,因此可以使用intern方法主動將還沒有放入字符串常量池的對象放入該常量池

    • 1.8 將這個字符串對象嘗試放入串池,如果有則并不會放入,如果沒有則放入串池, 會把字符串常量池中的對象返回
    • 1.6 將這個字符串對象嘗試放入串池,如果有則并不會放入,如果沒有會把此對象復(fù)制一份,放入字符串常量池, 并把該對象返回

    說說JVM的運行時內(nèi)存

    根據(jù)GC的角度來劃分的話,堆內(nèi)存又劃分為新生代和老年代。

    新生代

    新生代一般存放新生的內(nèi)存對象,大約占用堆內(nèi)存的1/3,如果新生的對象內(nèi)存過大,將會存放在老年代中。在新生代中會觸發(fā)MinorGC,新生代分為eden區(qū)、from survivor、to survivor區(qū)

    eden區(qū):

    中文翻譯為伊甸園,即亞當(dāng)和夏娃的原住地,因此寓意為Java對象的出生地。當(dāng)新的Java對象過大時,會在老年代產(chǎn)生新對象;當(dāng)內(nèi)存不足時,就會觸發(fā)MinorGC,此時如果內(nèi)存還無法容納新對象,就會發(fā)生錯誤。

    from survivor:上一次 GC 的幸存者,作為這一次 GC 的被掃描者。

    to survivo:保留了一次 MinorGC 過程中的幸存者

    談?wù)劺厥账惴?/h3>

    確定對象是否能被回收的方法:引用計數(shù)法、可達性分析法

    引用計數(shù)法

    在Java中,對象是通過引用進行關(guān)聯(lián)的。當(dāng)需要操作一個對象時,就對該對象的引用計數(shù)+1,當(dāng)操作完時,就對該對象的計數(shù)-1;這種通過引用計數(shù)的方式來判斷對象是否可以被回收的方法就稱為引用計數(shù)法。當(dāng)一個對象計數(shù)為0時,則表明該對象可以被垃圾回收。

    弊端:

    當(dāng)對象循環(huán)引用時會造成對象無法被垃圾回收,從而發(fā)送內(nèi)存泄漏。因此,Java虛擬機沒有采用引用計數(shù)法。

    可達性分析法

    以GC Roots對象作為起始點開始向下搜索,如果一些對象沒有被GC Roots所引用,那么就說這些對象是不可達的,因此可以判定該對象為可回收對象。

    就好比盤子里的葡萄,用手提起葡萄根,連在根上沒有掉落的葡萄就是可達的,散落在盤子上的就稱為不可達的,因此在盤子上的葡萄就是可以被回收的。

    哪些對象可以作為GC Roots對象呢?

    • Java虛擬機棧幀內(nèi)所引用的對象
    • 方法區(qū)中被static修飾的對象
    • 本地方法棧的對象
    • 被上鎖的對象

    垃圾回收算法:標記清除、標記整理、copy算法

    標記清除

    該垃圾回收算法分為兩個階段,標注和清除。標記階段標記出所有需要回收的對象,清除階段回收被標記的對象所占用的空間。

    標記:如上圖,先對需要回收的垃圾對象標記為黑色()

    清除:隨后將該內(nèi)存清除

    弊端:內(nèi)存碎片化問題嚴重

    標記整理

    根據(jù)老年代的特點提出的一種標記算法,標記過程仍然與“標記-清除”算法一樣,但后續(xù)是讓所有存活的對象向一端移動,然后直接清理掉端邊界以外的內(nèi)存。

    該算法分為兩步:標記、整理

    如圖,先對可回收的對象進行標記

    與標記清除算法不同的是,標記整理第二步會將之前的對象往前挪動,使得對象之間的間隔更為緊湊,從而減少內(nèi)存碎片的問題。

    弊端:雖然減少了內(nèi)存碎片,但是因為需要挪動對象,造成了性能上的損耗。

    復(fù)制Copy算法

    為了解決效率問題,。它可以將內(nèi)存分為大小相同兩塊,每次使用其中的一塊。當(dāng)這一塊的內(nèi)存使用完后,就將還存活的對象復(fù)制到另一塊去,然后再把使用的空間一次清理掉。這樣就使每次的內(nèi)存回收都是對內(nèi)存區(qū)間的一半進行回收。

    步驟:

    • 將內(nèi)存區(qū)域分為兩塊,分別為from,to
    • 對象一開始在from區(qū)域,該區(qū)域內(nèi)存使用完發(fā)起垃圾回收時,將存活的對象復(fù)制到to區(qū)域
    • 清除from區(qū)域的全部垃圾,同時將from和to的內(nèi)存區(qū)域?qū)φ{(diào)
    • 原來的to改為from,from改為to

    分代回收算法

    分代回收算法的特點就是根據(jù)對象的生命周期不同,將存放對象的區(qū)域劃分為新生代和老年代。

    在新生代中,每次收集都會有大量對象死去,所以可以選擇復(fù)制算法,只需要付出少量對象的復(fù)制成本就可以完成每次垃圾收集。而老年代的對象存活幾率是比較高的,而且沒有額外的空間對它進行分配擔(dān)保,所以我們必須選擇**“標記-清除”或“標記-整理”**算法進行垃圾收集

    老生代

    特點是每次垃圾回收時只有少量對象需要被回收,存放在老年代的對象一般為頻繁使用或占用內(nèi)存較大的對象

    新生代

    特點是每次垃圾回收時會有大量的對象需要被回收,絕大部分新生對象在新生代。

    新生代劃分了三個區(qū)域,分別是Eden、from survivor、to survivor


    新生代使用了Copy算法對內(nèi)存對象進行回收。
    流程:

    • 新生對象在伊甸園出生
    • 當(dāng)觸發(fā)MinorGc時,會將幸存下來的對象放入from,未被回收的對象的年齡+1
    • 對調(diào)from和to的內(nèi)存地址,把原來的from變?yōu)閠o,to變?yōu)閒rom

    四種引用類型

    強引用

    在Java中,我們最長見到的就是強引用。所謂強引用,就是把一個對象賦給一個引用變量,該對象就稱為被強引用的對象。一個強引用對象,它是處于可達的狀態(tài),因此該對象是不能被垃圾回收的。

    軟引用

    軟引用需要用 SoftReference 類來實現(xiàn),對于只有軟引用的對象來說,當(dāng)系統(tǒng)內(nèi)存足夠時它不會被回收,當(dāng)系統(tǒng)內(nèi)存空間不足時它會被回收。軟引用通常用在對內(nèi)存敏感的程序中。

    弱引用

    弱引用需要用 WeakReference 類來實現(xiàn),它比軟引用的生存期更短,對于只有弱引用的對象來說,只要垃圾回收機制一運行,不管 JVM 的內(nèi)存空間是否足夠,總會回收該對象占用的內(nèi)存。

    虛引用

    虛引用需要 PhantomReference 類來實現(xiàn),它不能單獨使用,必須和引用隊列聯(lián)合使用。 虛引用的主要作用是跟蹤對象被垃圾回收的狀態(tài)

    總結(jié):

    強軟弱虛,強的不能被回收,軟的當(dāng)系統(tǒng)內(nèi)存不足時被被回收,弱的不管內(nèi)存夠不夠都會被回收,虛的還需要結(jié)合引用隊列來回收。

    引用類型被回收時間用途生存時間
    強引用不會被回收對象的一般狀態(tài)JVM停止運行時
    軟引用內(nèi)存不足時被回收對象緩存內(nèi)存不足時
    弱引用無論內(nèi)存是否不足都被回收對象緩存垃圾回收后
    虛引用未知-需要結(jié)合引用隊列使用未知未知

    垃圾回收器

    吞吐量
    CPU 用于運行用戶代碼的時間/CPU 總消耗時間,即吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)),高吞吐量可以最高效率地利用 CPU 時間,盡快地完成程序的運算任務(wù),主要適用于在后臺運算而不需要太多交互的任務(wù)

    常見的垃圾回收器有:

    Serial,翻譯為連續(xù)的,是最基本的新生代垃圾收集器,單線程,使用了復(fù)制算法,當(dāng)發(fā)生垃圾回收的時候會暫停其他線程的活動(stop the world)

    ParNew,Serial垃圾收集器的多線程版本,使用了復(fù)制算法

    Parallel Scavenge**,是一個新生代垃圾收集器,使用了復(fù)制算法,是一個多線程的垃圾收集器,它重點關(guān)注的是程序達到一個可控制的吞吐量。

    Serial Old,與Serial一樣是單線程的垃圾收集器,作用于老年代,使用標記整理算法

    Parallel Old ,是Parallel Scavenge的年老代版本,使用多線程的標記-整理算法,在 JDK1.6才開始提供,提供一個關(guān)注吞吐量的模式。

    CMS ,是一種老年代垃圾收集器,其最主要目標是獲取最短垃圾
    回收停頓時間,它使用多線程的標記-清除算法。最短的垃圾收集停頓時間可以為交互比較高的程序提高用戶體驗

    G1基于標記-整理算法,不產(chǎn)生內(nèi)存碎片,可以非常精確控制停頓時間,在不犧牲吞吐量前提下,實現(xiàn)低停頓垃圾回收。G1 收集器避免全區(qū)域垃圾收集,它把堆內(nèi)存劃分為大小固定的幾個獨立區(qū)域,并且跟蹤這些區(qū)域的垃圾收集進度,同時在后臺維護一個優(yōu)先級列表,每次根據(jù)所允許的收集時間,優(yōu)先回收垃圾最多的區(qū)域

    Full GC 觸發(fā)條件

  • 調(diào)用 System.gc():只是建議虛擬機執(zhí)行 Full GC,但是虛擬機不一定真正去執(zhí)行。不建議使用這種方式,而是讓虛擬
    機管理內(nèi)存。
  • 老年代空間不足: 老年代空間不足的常見場景為前文所講的大對象直接進入老年代、長期存活的對象進入老年代
    等。為了避免以上原因引起的 Full GC,應(yīng)當(dāng)盡量不要創(chuàng)建過大的對象以及數(shù)組。除此之外,可以通過 -Xmn 虛擬
    機參數(shù)調(diào)大新生代的大小,讓對象盡量在新生代被回收掉,不進入老年代。還可以通過 -XX:MaxTenuringThreshold
    調(diào)大對象進入老年代的年齡,讓對象在新生代多存活一段時間。
  • 空間分配擔(dān)保失敗: 使用復(fù)制算法的 Minor GC 需要老年代的內(nèi)存空間作擔(dān)保,如果擔(dān)保失敗會執(zhí)行一次 Full GC。
  • JDK1.7 以及以前的永久代空間不足:在 JDK 1.7 及以前, HotSpot 虛擬機中的方法區(qū)是用永久代實現(xiàn)的,永久代
    中存放的為一些 Class 的信息、常量、靜態(tài)變量等數(shù)據(jù)。 當(dāng)系統(tǒng)中要加載的類、反射的類和調(diào)用的方法較多時,
    永久代可能會被占滿,在未配置為采用 CMS GC 的情況下也會執(zhí)行 Full GC。如果經(jīng)過 Full GC 仍然回收不了,
    那么虛擬機會拋出 java.lang.OutOfMemoryError。 為避免以上原因引起的 Full GC,可采用的方法為增大永久代空
    間或轉(zhuǎn)為使用 CMS GC。
  • Concurrent Mode Failure: 執(zhí)行 CMS GC 的過程中同時有對象要放入老年代,而此時老年代空間不足(可能是 GC
    過程中浮動垃圾過多導(dǎo)致暫時性的空間不足),便會報 Concurrent Mode Failure 錯誤,并觸發(fā) Full GC
  • 對象創(chuàng)建過程

  • 類加載檢驗: 虛擬機遇到一條 new 指令時,首先將去檢查這個指令的參數(shù)是否能在常量池中定位到這個類的符號
    引用,并且檢查這個符號引用代表的類是否已被加載過、解析和初始化過。如果沒有,那必須先執(zhí)行相應(yīng)的類加載
    過程。
  • 分配內(nèi)存:分配方式有“指針碰撞”和“空閑列表”兩種,選擇哪種分配方式由 Java 堆是否規(guī)整決定,而 Java 堆是
    否規(guī)整又由所采用的垃圾收集器是否帶有壓縮整理功能決定。 標記-清理不規(guī)整,標記-整理以及復(fù)制算法是規(guī)整
    的。在創(chuàng)建對象的時候有一個很重要的問題,就是線程安全,因為在實際開發(fā)過程中,創(chuàng)建對象是很頻繁的事情,
    作為虛擬機來說,必須要保證線程是安全的,通常來講,虛擬機采用兩種方式來保證線程安全:
    CAS+失敗重試: CAS 是樂觀鎖的一種實現(xiàn)方式。所謂樂觀鎖就是,每次不加鎖而是假設(shè)沒有沖突而去完成某項
    操作,如果因為沖突失敗就重試,直到成功為止。虛擬機采用 CAS 配上失敗重試的方式保證更新操作的原子性。
    TLAB: 為每一個線程預(yù)先在 Eden 區(qū)分配一塊兒內(nèi)存, JVM 在給線程中的對象分配內(nèi)存時,首先在 TLAB 分配,
    當(dāng)對象大于 TLAB 中的剩余內(nèi)存或 TLAB 的內(nèi)存已用盡時,再采用上述的 CAS 進行內(nèi)存分配
  • 初始化零值: 內(nèi)存分配完成后,虛擬機需要將分配到的內(nèi)存空間的對象都初始化為零值(不包括對象頭),這一步
    操作保證了對象的實例字段在 Java 代碼中可以不賦初始值就直接使用,程序能訪問到這些字段的數(shù)據(jù)類型所對
    應(yīng)的零值。85
  • 設(shè)置對象頭: 初始化零值完成之后,虛擬機要對對象進行必要的設(shè)置,例如這個對象是哪個類的實例、 如何才能找
    到類的元數(shù)據(jù)信息、 對象的哈希碼、 對象的 GC 分代年齡等信息。 這些信息存放在對象頭中。 另外,根據(jù)虛擬
    機當(dāng)前運行狀態(tài)的不同,如是否啟用偏向鎖等,對象頭會有不同的設(shè)置方式。
  • 執(zhí)行 init 方法: 在上面工作都完成之后,從虛擬機的視角來看,一個新的對象已經(jīng)產(chǎn)生了,但從 Java 程序的視角
    來看,對象創(chuàng)建才剛開始, 方法還沒有執(zhí)行,所有的字段都還為零。所以一般來說,執(zhí)行 new 指令之后會
    接著執(zhí)行 方法,把對象按照程序員的意愿進行初始化,這樣一個真正可用的對象才算完全產(chǎn)生出來
  • 對象已經(jīng)死亡

  • 引用計數(shù)法: 給對象中添加一個引用計數(shù)器,每當(dāng)有一個地方引用它,計數(shù)器就加 1;當(dāng)引用失效,計數(shù)器就減
    1;任何時候計數(shù)器為 0 的對象就是不可能再被使用的。 很難解決對象之間相互循環(huán)引用的問題。
  • 可達性分析法: 這個算法的基本思想就是通過一系列的稱為 “GC Roots” 的對象作為起點,從這些節(jié)點開始向下搜
    索,節(jié)點所走過的路徑稱為引用鏈,當(dāng)一個對象到 GC Roots 沒有任何引用鏈相連的話,則證明此對象是不可用
    的。
    兩次標記過程:即第一次標記可達性分析法中不可達的對象。第二次的話就要先判斷該對象有沒有實現(xiàn) finalize()方
    法了,如果沒有實現(xiàn)就直接判斷該對象可回收;如果實現(xiàn)了就會先放在一個隊列中,并由虛擬機建立的一個低優(yōu)
    先級的線程去執(zhí)行它,隨后就會進行第二次的小規(guī)模標記,在這次被標記的對象就會真正的被回收了。
  • 類的加載過程

    類的加載過程分別為:加載 -> 連接 -> 初始化 -> 使用 -> 卸載

    在連接過程中又分為:驗證 -> 準備 ->解析

    加載:主要完成下面三件事情:通過全類名獲得定義此類的二進制字節(jié)流,在內(nèi)存中生成一個代表該類的 Class 對象,作為方法區(qū)這些數(shù)據(jù)的訪問入口。

    驗證:文件格式驗證、元數(shù)據(jù)驗證、字節(jié)碼驗證、符號引用驗證

    準備: 準備階段是正式為類變量分配內(nèi)存并設(shè)置類變量初始值的階段,這些內(nèi)存都將在方法區(qū)中分配。 進行內(nèi)存分配
    的對象僅包括類變量(static),不包括實例變量;設(shè)置的初始值“通常情況”下是數(shù)據(jù)類型默認的零值,但是加上 final 之
    后,就會在這個階段賦值具體值。

    解析: 解析階段是虛擬機將常量池內(nèi)的符號引用替換為直接引用的過程。 符號引用就是一組符號來描述目標,可以是
    任何字面量。 直接引用就是直接指向目標的指針、相對偏移量或一個間接定位到目標的句柄。

    初始化:必須進行初始化的五種情況:

  • 當(dāng)遇到 new 、 getstatic、 putstatic 或 invokestatic 這 4 條直接碼指令時,比如 new 一個類,讀取一個靜
    態(tài)字段(未被 final 修飾)、或調(diào)用一個類的靜態(tài)方法時。

  • 使用 java.lang.reflect 包的方法對類進行反射調(diào)用時如 Class.forname("…"),newInstance()

  • 初始化一個類, 如果其父類還未初始化,則先觸發(fā)該父類的初始化。

  • 當(dāng)虛擬機啟動時,用戶需要定義一個要執(zhí)行的主類 (包含 main 方法的那個類), 虛擬機會先初始化這個類。

  • MethodHandle 和 VarHandle 可以看作是輕量級的反射調(diào)用機制,而要想使用這 2 個調(diào)用, 就必須先使用
    findStaticVarHandle 來初始化要調(diào)用的類

  • 談?wù)勵惣虞d過程的雙親委托機制?

    類加載器
    JVM 中內(nèi)置了三個重要的 ClassLoader,除了 BootstrapClassLoader 其他類加載器均由 Java 實現(xiàn)且全部繼承自
    java.lang.ClassLoader:

    BootstrapClassLoader(啟動類加載器) :最頂層的加載類,由 C++實現(xiàn),負責(zé)加載 %JAVA_HOME%/lib 目錄下的 jar 包
    和類或者或被 -Xbootclasspath 參數(shù)指定的路徑中的所有類。 加載一些通用的類: Object 類等。

    ExtensionClassLoader(擴展類加載器) :主要負責(zé)加載目錄 %JRE_HOME%/lib/ext 目錄下的jar包和類,或被 java.ext.dirs
    系統(tǒng)變量所指定的路徑下的 jar 包。

    AppClassLoader(應(yīng)用程序類加載器) :面向我們用戶的加載器,負責(zé)加載當(dāng)前應(yīng)用 classpath 下的所有 jar 包和類。
    Main 類是在 AppClassLoader 里面加載的

    雙親委派模型
    每一個類都有一個對應(yīng)它的類加載器。系統(tǒng)中的 ClassLoder 在協(xié)同工作的時候會默認使用 雙親委派模型 。

    雙親委派模型要求除了頂層的啟動類加載器外,其余的類加載器都應(yīng)當(dāng)應(yīng)當(dāng)有自己的父類加載器。這里的類加載
    器之間的父子關(guān)系一般不會以繼承的關(guān)系來實現(xiàn),而是使用組合關(guān)系來復(fù)用父類加載器的代碼。

    AppClassLoader 的父類加載器為 ExtClassLoader

    ExtClassLoader 的父類加載器為 null, null 并不代表 ExtClassLoader 沒有父類加載器,而是 BootstrapClassLoader。
    在類加載的時候,系統(tǒng)會首先判斷當(dāng)前類是否被加載過。已經(jīng)被加載的類會直接返回,否則才會嘗試加載。

    加載的時候,首先會把該請求委派該父類加載器的 loadClass() 處理,因此所有的請求最終都應(yīng)該傳送到頂層的啟動類加載
    器 BootstrapClassLoader 中。當(dāng)父類加載器無法處理時,才由自己來處理。當(dāng)父類加載器為 null 時,會使用啟動類加
    載器 BootstrapClassLoader 作為父類加載器

    雙親委派機制的好處

    雙親委派模型保證了 Java 程序的穩(wěn)定運行,可以避免類的重復(fù)加載

    保證了 Java 的核心 API 不被篡改。如果沒有使用雙親委派模型 ,而是每個類加載器加載自己的話就會出現(xiàn)一些問題 ,比如我們編寫一個稱為java.lang.Object 類的話,那么程序運行的時候,系統(tǒng)就會出現(xiàn)多個不同的 Object 類。

    如何破壞

    自定義加載器的話,需要繼承 ClassLoader 。如果我們不想打破雙親委派模型,就重寫 ClassLoader 類中的 findClass() 方法即可,無法被父類加載器加載的類最終會通過這個方法被加載。但是,如果想打破雙親委派模型則需要重寫 loadClass() 方法

    JVM的內(nèi)存模型

    Java 內(nèi)存區(qū)域和內(nèi)存模型是不一樣的東西,內(nèi)存區(qū)域是指 Jvm 運行時將數(shù)據(jù)分區(qū)域存儲,強調(diào)對內(nèi)存空間的劃分。

    內(nèi)存模型(Java Memory Model,簡稱 JMM )是定義了線程和主內(nèi)存之間的抽象關(guān)系,即 JMM 定義了 JVM 在計算機內(nèi)存(RAM)中的工作方式。

    Java 內(nèi)存模型(Java Memory Model,JMM)是 java 虛擬機規(guī)范定義的,用來屏蔽掉 java 程序在各種不同的硬件和操作系統(tǒng)對內(nèi)存的訪問的差異,這樣就可以實現(xiàn) java 程序在各種不同的平臺上都能達到內(nèi)存訪問的一致性??梢员苊庀?c等直接使用物理硬件和操作系統(tǒng)的內(nèi)存模型在不同操作系統(tǒng)和硬件平臺下表現(xiàn)不同,比如有些 c/c程序可能

    在 windows 平臺運行正常,而在 linux 平臺卻運行有問題

    JVM性能調(diào)優(yōu)常用命令

    工具: JConsole: Java 監(jiān)視與管理控制臺

    Visual VM:多合一故障處理工具

    命令: jps (JVM Process Status) : 類似 UNIX 的 ps 命令。用戶查看所有 Java 進程的啟動類、傳入?yún)?shù)和 Java 虛擬
    機參數(shù)等信息;

    jstat( JVM Statistics Monitoring Tool) : 用于收集 HotSpot 虛擬機各方面的運行數(shù)據(jù);

    jinfo (Configuration Info for Java) : Configuration Info forJava,顯示虛擬機配置信息;

    jmap (Memory Map for Java) :生成堆轉(zhuǎn)儲快照;

    jhat (JVM Heap Dump Browser ) : 用于分析 heapdump 文件,它會建立一個 HTTP/HTML 服務(wù)器,讓用戶可以在
    瀏覽器上查看分析結(jié)果;

    jstack (Stack Trace for Java):生成虛擬機當(dāng)前時刻的線程快照,線程快照就是當(dāng)前虛擬機內(nèi)每一條線程正在執(zhí)行的
    方法堆棧的集合

    總結(jié)

    以上是生活随笔為你收集整理的Java全链路复习面经-基础篇(2.5万字全文)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    又污又黄的网站 | 亚洲精品视频偷拍 | 国产精品18久久久久久久久久久久 | 超碰在线98| 91精品资源 | 午夜视频色 | 视频在线观看日韩 | 五月综合在线观看 | 日韩女同av | 久久久国产影视 | 成年人免费看片 | www.com在线观看 | 国产高清视频在线 | 国产亚洲视频系列 | 国产第页 | 国产特级毛片aaaaaa毛片 | 天天爱天天舔 | 欧美日韩国产一区 | 亚洲人成免费网站 | 欧美了一区在线观看 | 在线免费观看国产黄色 | 国产精品短视频 | 久久在线视频精品 | 欧美色图p| 久久久久久久久免费 | 日韩在线观看一区二区三区 | 国产91在线观看 | 亚洲成人第一区 | 999电影免费在线观看2020 | 日日草av| 国产麻豆视频 | 精品国产成人在线影院 | 四虎最新入口 | 天天爱天天舔 | 欧洲一区二区在线观看 | 国产又粗又猛又爽又黄的视频免费 | aaa毛片视频 | 日韩在线激情 | 亚洲国产中文字幕在线观看 | 毛片视频网址 | 中文字幕在线看片 | 国产精品自产拍 | 免费视频三区 | 国产精品高清一区二区三区 | 久久香蕉国产 | 麻豆果冻剧传媒在线播放 | 性色av香蕉一区二区 | 亚洲欧洲精品在线 | 久综合网 | www免费 | 嫩草av影院 | 中文字幕免费一区 | 久久九九免费视频 | 亚洲更新最快 | 在线观看网站黄 | 99久久综合狠狠综合久久 | 丁香久久五月 | 91香蕉视频黄色 | 国产探花 | 天天射网 | 国产视频在线播放 | 亚洲一区欧美激情 | 91资源在线观看 | 超碰公开97 | 在线播放 亚洲 | 精品一区二区在线观看 | 免费国产在线视频 | 日韩国产精品毛片 | 激情久久久久久久久久久久久久久久 | 久久视频一区 | 91精品国产99久久久久久红楼 | 丁香婷婷综合网 | 日韩欧美在线第一页 | www.亚洲视频| 99久久爱 | 天堂网av在线| 夜夜澡人模人人添人人看 | 日本中文在线观看 | 激情综合色图 | 日韩欧美黄色网址 | 狠狠亚洲| 91在线视频免费91 | 欧美久久久影院 | 久久精品影视 | 黄色午夜 | 天天操偷偷干 | 一级片免费观看 | 美女视频a美女大全免费下载蜜臀 | 日本公妇在线观看高清 | 国产一卡久久电影永久 | 成人黄色资源 | 91刺激视频 | www.久草.com | 天天草网站 | 亚洲理论在线观看 | 在线中文字幕观看 | 国产精品久久久久aaaa九色 | 99视频在线精品免费观看2 | 欧美黑吊大战白妞欧美 | 天天干天天干天天干 | 丁香婷婷激情网 | 国产黄色片免费在线观看 | 激情五月婷婷激情 | 免费在线观看亚洲视频 | 精品美女在线视频 | 日韩久久精品一区 | 特级毛片网 | 日韩精品久久久久久中文字幕8 | 精品国产三级a∨在线欧美 免费一级片在线观看 | 中文字幕丰满人伦在线 | 色婷婷视频网 | 中文字幕久久亚洲 | 高潮毛片无遮挡高清免费 | 国产91大片| 中文字幕在线国产精品 | 精品久操 | 久久在线视频在线 | 九九久久国产精品 | 欧美网址在线观看 | 九九视频免费在线观看 | 国产又粗又硬又长又爽的视频 | av免费看网站| 久久久精品电影 | 久久久av免费 | 91探花系列在线播放 | a极黄色片 | 日韩欧美一区视频 | 国产精品色婷婷视频 | 天天干夜夜爽 | 精品久久久久久久久久久久久久久久 | 99精品热 | 国产99久久久国产精品成人免费 | 久久久久亚洲精品国产 | 国产精品中文久久久久久久 | 日韩www在线| 在线看成人| 黄色日视频| bbw av| 一本一本久久aa综合精品 | 精品久久一区 | 美女一区网站 | 国产精品一区二区精品视频免费看 | 国内丰满少妇猛烈精品播放 | 亚洲永久精品视频 | 99精品免费久久久久久久久 | 国产91全国探花系列在线播放 | 国产99在线播放 | 亚洲一级黄色 | 粉嫩av一区二区三区免费 | 国产精品久久久久久久久大全 | 日韩黄色在线电影 | 国产尤物在线 | 国产中文字幕视频在线观看 | 欧美日韩国产精品一区二区亚洲 | 日本久久综合网 | 亚洲一级黄色大片 | 91人网站| 中文字幕亚洲精品日韩 | 国产精品午夜8888 | 国产视频精品免费播放 | 久久综合导航 | av在线免费在线观看 | 国产另类xxxxhd高清 | 视频在线99 | 中文字幕在线免费 | www国产亚洲精品久久网站 | www夜夜操com | 99久e精品热线免费 99国产精品久久久久久久久久 | 91桃色国产在线播放 | 免费观看性生交 | 黄色小说在线免费观看 | 91av片 | 91精品国自产在线观看欧美 | 国产亚洲成av人片在线观看桃 | 人人爱人人舔 | 国产成a人亚洲精v品在线观看 | 嫩小bbbb摸bbb摸bbb | 夜夜夜夜操 | 久久成视频| 欧美a级免费视频 | 亚洲免费av电影 | 国产在线观 | 丝袜美女在线 | 国产视频1区2区3区 久久夜视频 | 96超碰在线 | 久久超 | 国产精品久久久一区二区 | 久久久久久久久久网站 | 国产精品久久久久婷婷二区次 | 国内久久 | 成人网在线免费视频 | 欧美日韩中文字幕在线视频 | 中文字幕日韩免费视频 | 久久成人18免费网站 | 天天综合网 天天 | 麻豆视频国产精品 | 伊人黄色网 | 午夜国产福利视频 | 黄色av免费| 99超碰在线播放 | 久久精品三级 | 色综合天天做天天爱 | 久久y| 久久桃花网 | 精品免费99久久 | 字幕网在线观看 | 韩国一区在线 | 网址你懂的在线观看 | 国产亚洲精品无 | 天天操天天操天天操天天操天天操 | 国产美女精彩久久 | 友田真希x88av | 国产精品久久久久久久电影 | 色多多视频在线 | 久草网首页 | 久久精品国产精品 | 色婷久久 | 狠狠色2019综合网 | 日日爽 | 天天干天天摸 | 国产在线播放观看 | 日韩精品无 | 亚洲在线视频免费 | 久久97超碰 | 999久久国产精品免费观看网站 | 99精品国产免费久久久久久下载 | 婷婷电影在线观看 | 中文字幕在线观看完整版 | 免费成视频 | 一级性生活片 | 亚洲日本在线一区 | 99精品视频在线观看免费 | 天天爱天天干天天爽 | 伊人狠狠色丁香婷婷综合 | 久久久久亚洲天堂 | 久久久久久久亚洲精品 | www.色婷婷 | 91视频在线观看下载 | 日韩精品久久一区二区三区 | 国产电影一区二区三区四区 | 96国产精品| 精品国模一区二区三区 | 亚洲精品视频一二三 | 日日夜夜操av | 又黄又刺激视频 | 精品国产一区二区三区av性色 | 最新国产中文字幕 | 欧美激情精品一区 | 视频一区二区在线 | 久久视奸| 久久高视频 | 丁香5月婷婷 | 欧美日韩一级在线 | 97超碰人人模人人人爽人人爱 | 亚洲女欲精品久久久久久久18 | 国产成人精品一区二区三区在线 | 日韩精品一卡 | 美女精品 | 视频一区在线免费观看 | 在线a视频免费观看 | 亚洲综合网 | 日韩黄色免费 | 日本公妇色中文字幕 | 久久精品观看 | 日韩大片免费在线观看 | www一起操| 永久精品视频 | 男女拍拍免费视频 | 在线欧美日韩 | 精品在线免费视频 | 久久久久久久久亚洲精品 | 九九九热精品免费视频观看 | 日韩av影片在线观看 | 国产99久久久国产精品免费看 | 久久99国产精品久久99 | 一区二区三区在线观看 | 亚洲第一区在线观看 | 91porny九色在线播放 | 免费av试看| 国产精品成人一区二区三区吃奶 | av 在线观看 | 色噜噜日韩精品一区二区三区视频 | 91人人澡| av黄色亚洲 | 天天操夜夜操 | 麻花豆传媒mv在线观看 | 干天天| 日韩电影在线一区 | 亚洲免费不卡 | 国产高清免费在线观看 | 视频在线观看一区 | 国产91九色蝌蚪 | 伊人五月在线 | 四虎免费av | 亚洲作爱视频 | 黄色一级大片在线免费看产 | 中文字幕亚洲欧美日韩2019 | 欧美在线视频一区二区 | 涩涩网站在线播放 | 西西www4444大胆在线 | 免费精品人在线二线三线 | 在线99 | 精品天堂av | 国产日韩在线看 | 一区二区三区精品在线视频 | 中文字幕视频播放 | 91精品一区二区三区蜜桃 | 九九九九精品九九九九 | 在线a亚洲视频播放在线观看 | 天天干中文字幕 | 久久伊人免费视频 | 91av网址 | 欧美另类重口 | 日日摸日日碰 | 国产精品麻豆91 | 久久精国产 | 三三级黄色片之日韩 | 中文字幕在线观看免费高清完整版 | 国产不卡高清 | 国产亚洲精品久久久久久久久久久久 | 亚洲视频精品 | 91私密保健 | 色国产精品一区在线观看 | 国产中文字幕三区 | 国产一区二区三精品久久久无广告 | 免费a视频在线观看 | 亚欧日韩av | 日韩在线小视频 | 免费看黄在线看 | 九九免费精品视频在线观看 | 九九九九热精品免费视频点播观看 | 欧美日韩精品在线一区二区 | 91欧美日韩国产 | 欧美性大战| 久久久久久不卡 | 亚洲综合视频网 | 亚洲特级片 | 伊人国产视频 | 日韩av手机在线看 | 色婷婷五| 色综合久久精品 | 91在线资源| 亚洲国产精品视频在线观看 | 久久综合电影 | 在线视频一区二区 | 亚洲色综合 | 亚洲免费av观看 | 五月综合在线观看 | 国产精品女视频 | 国产精品久久久久久久久久久久午 | 日韩欧美一区二区三区黑寡妇 | 九月婷婷人人澡人人添人人爽 | 久久激情视频 | 色爽网站 | 超碰97中文 | 久久成人久久 | 久久久久99精品成人片三人毛片 | 日本中文字幕电影在线免费观看 | 国产精品黄色 | 日韩美女黄色片 | 国产一区二区综合 | 黄色一级片视频 | 天天鲁一鲁摸一摸爽一爽 | 亚洲女裸体| 欧美一区二区免费在线观看 | 射九九| 国产粉嫩在线 | 免费99视频 | 久久国产精品免费一区二区三区 | 日韩免费在线观看视频 | 91一区在线观看 | 国产在线精品福利 | 二区三区精品 | 99精品视频在线观看免费 | 99精品国产在热久久 | 久久久久久久久毛片精品 | 在线视频亚洲 | 一区二区三区免费在线播放 | 欧美极品久久 | 日日操天天操狠狠操 | 91黄色免费网站 | 97视频网站| 午夜av剧场 | 日韩精品免费在线视频 | 久久久久久久av麻豆果冻 | 97超碰国产在线 | 中文字幕 影院 | 久久久久久久网站 | 人人舔人人爱 | 激情视频一区二区三区 | 亚州欧美视频 | 日韩系列 | 欧美日韩性视频 | 欧美a级免费视频 | 91九色最新 | 日韩成片| 91在线免费播放 | 久久久久久美女 | 国产小视频国产精品 | 狠狠干综合 | 丁香午夜| 99精品欧美一区二区三区黑人哦 | 伊人激情网 | 伊人狠狠干 | 欧美色黄 | 日韩美女黄色片 | 日韩欧美有码在线 | 69国产在线观看 | 日韩在线观看视频一区二区三区 | 欧美日韩国产三级 | 韩国精品在线 | 亚洲高清在线 | 91精品国产网站 | 亚洲视频精品 | 久久久午夜精品福利内容 | 免费成人在线网站 | 国产午夜精品一区二区三区四区 | 久久久久久久久久久久久9999 | 国产精品综合在线 | 在线影院中文字幕 | 久久精品精品电影网 | 国产福利av在线 | 国产精品久久久久久久久久久免费 | 激情网五月 | 亚洲激情婷婷 | 91麻豆视频网站 | 久久精品视频在线观看免费 | 欧美日高清视频 | 中文字幕在线看视频国产中文版 | 天天做天天干 | 国产在线观看你懂的 | 亚洲第五色综合网 | 婷婷色社区 | 亚洲精品中文在线 | 欧美日韩后 | 亚洲欧美国产精品18p | 国产精品理论片在线播放 | 美女免费视频一区 | 国内三级在线观看 | 成片免费观看视频999 | 午夜av色| 成人免费xxx在线观看 | 国产精品完整版 | a久久久久 | 韩日av一区二区 | 亚洲国产三级在线观看 | 国产午夜精品一区二区三区欧美 | 国产精品免费视频网站 | 麻豆传媒在线视频 | www.国产高清 | 伊人五月在线 | 亚洲一级电影在线观看 | 天操夜夜操 | 久久久久女人精品毛片 | 手机在线看片日韩 | 亚洲人成网站精品片在线观看 | 国产69精品久久久久久 | 国产三级国产精品国产专区50 | 国产精品一区二区久久国产 | 在线免费国产视频 | 992tv在线观看| 国产精品白丝jk白祙 | 字幕网资源站中文字幕 | 国产一区在线免费观看 | 国产 日韩 在线 亚洲 字幕 中文 | av大片免费看| 99久久精品免费看国产一区二区三区 | 欧美性受极品xxxx喷水 | 免费网站在线观看成人 | www.com在线观看 | 亚洲精品乱码久久久久v最新版 | 欧美精品一区二区三区一线天视频 | 十八岁以下禁止观看的1000个网站 | 成人a v视频 | 五月婷婷欧美视频 | 欧美日韩18 | 欧洲精品码一区二区三区免费看 | av在线播放观看 | 日韩精品中文字幕在线观看 | 伊人久久国产 | 亚洲精品资源 | 色婷婷综合久久久久中文字幕1 | 欧美亚洲成人xxx | 一区二区视频免费在线观看 | 久久久亚洲网站 | 91伊人影院 | 欧美日韩三级在线观看 | 天天色视频 | 99精品系列 | 国精产品一二三线999 | 最新av网址在线观看 | 超碰97av在线| 精品久久久久久亚洲综合网站 | 天天天在线综合网 | 亚洲精品视频在线观看免费视频 | 不卡电影免费在线播放一区 | 国产三级在线播放 | 亚洲精品啊啊啊 | 日韩黄色av网站 | 黄色精品国产 | 日韩视频1区 | www.一区二区三区 | 在线观看免费av片 | 狠狠狠色丁香婷婷综合久久五月 | 人人擦 | 91免费视频国产 | 不卡av在线播放 | 日日干美女 | 欧美a在线免费观看 | 97人人网| 亚洲五月婷婷 | 久久久久一区二区三区四区 | 人人爱人人舔 | 久久999久久 | 精品一二三区视频 | 欧美a级在线 | 国产精品免费成人 | 韩国av一区二区三区在线观看 | 国产三级午夜理伦三级 | 7799av | 麻豆视频在线观看免费 | 麻豆传媒视频在线播放 | 波多野结衣在线视频免费观看 | 97在线看片 | 一区二区三区播放 | 99精品视频在线观看免费 | 天天爱天天舔 | 婷婷丁香色 | 日本久久久久久久久久 | 操夜夜操| 香蕉视频导航 | 探花视频免费观看 | 一区二区三区电影大全 | 日韩电影中文字幕在线 | 色资源网在线观看 | 国产剧情在线一区 | 久久九九视频 | a级国产乱理伦片在线观看 亚洲3级 | 国产一区二区三区在线 | 国产做aⅴ在线视频播放 | 亚洲免费一级电影 | 日韩成人精品在线观看 | 手机成人av在线 | 在线免费色视频 | 99久视频 | 免费视频网 | 中文在线中文资源 | 国产h在线观看 | www.国产视频 | 999久久a精品合区久久久 | 国产精品wwwwww | 欧美不卡视频在线 | 麻豆传媒视频在线 | 这里只有精彩视频 | av千婊在线免费观看 | 97狠狠操| 在线观看中文字幕一区二区 | 91网在线观看 | 91av蜜桃| 欧美日韩a视频 | 国产精品区二区三区日本 | 成人91在线 | 日韩在线欧美在线 | 精品国产乱码一区二区三区在线 | 日本韩国精品在线 | 久久香蕉国产精品麻豆粉嫩av | 欧美精品一区二区在线播放 | 精品欧美一区二区精品久久 | 亚洲综合色丁香婷婷六月图片 | 一区二区激情 | 国产欧美日韩视频 | 91九色成人 | 伊人中文网 | 久草视频网 | 亚洲精品色视频 | 久久视频精品在线 | 日韩欧美一区二区三区在线 | 欧美性色综合网 | 天天爱天天草 | 亚洲国产日韩在线 | 国产视频69 | 久久第四色 | 麻豆综合网 | 久久天天躁狠狠躁夜夜不卡公司 | 日本公乱妇视频 | 亚洲精品在线视频 | 久久精品国产精品亚洲 | 国产精品正在播放 | 91视频在线免费看 | 日日夜夜操av | 国产成人av在线 | 婷婷久久亚洲 | 国产a精品 | 久久久久久毛片精品免费不卡 | 91福利在线观看 | 婷婷六月天丁香 | 亚洲片在线观看 | 91精品1区 | 精品96久久久久久中文字幕无 | 在线亚洲小视频 | 久久久久久久久电影 | 久久久免费看视频 | 久久久999免费视频 日韩网站在线 | 黄色在线免费观看网址 | 少妇性色午夜淫片aaaze | 国产精品1000 | 在线观看中文字幕一区 | 性色va | 久草在线视频中文 | 亚洲黄色在线播放 | 五月天久久婷婷 | 免费亚洲一区二区 | 亚洲另类xxxx | 国产欧美三级 | 开心激情五月婷婷 | 91精品免费在线观看 | 亚洲精品婷婷 | 狠狠干在线 | 欧美日本不卡视频 | 久久综合五月天婷婷伊人 | 999久久久久 | 在线有码中文 | 婷婷六月激情 | 99久久精品免费看国产四区 | www狠狠 | 中文字幕在线观看免费高清完整版 | 国产女人免费看a级丨片 | 伊人激情网 | 国产大片免费久久 | 日韩高清在线一区二区 | 日韩网站在线 | 在线播放精品一区二区三区 | 婷婷激情久久 | 中文字幕av免费 | 日韩专区中文字幕 | 国产精品一区久久久久 | 国产亚洲精品久久久久久移动网络 | 欧美一区成人 | 深夜免费福利网站 | 免费日韩视| 黄色三级网站 | 天天射天天干 | 97视频免费播放 | 国产免费午夜 | 在线看成人片 | 国产91对白在线播 | 国产黑丝一区二区三区 | 日本mv大片欧洲mv大片 | 亚洲精品麻豆视频 | 91色吧| 一级片免费在线 | 免费日韩 精品中文字幕视频在线 | 久久99精品久久久久蜜臀 | 久久久久久久免费 | 国产午夜三级一区二区三 | 久久综合亚洲鲁鲁五月久久 | 免费看黄的视频 | 成人cosplay福利网站 | 成人免费观看网站 | 成人黄色资源 | 欧美日韩免费一区 | 久久综合天天 | 成年人黄色免费视频 | 中文视频在线播放 | 天天操天天干天天玩 | 精品国产一区二区三区久久 | 日韩一级电影网站 | av在线播放中文字幕 | 成人黄色免费在线观看 | 国产成人精品av在线 | a级一a一级在线观看 | 色婷婷亚洲综合 | 精品国产乱子伦一区二区 | 91精品国产91 | 国产欧美在线一区 | 国产成人av网站 | 亚洲欧美日韩国产一区二区 | 久久久久久久影院 | 国产黄大片 | 久久在线免费视频 | 国产精品18久久久久久久网站 | 国产又粗又猛又黄又爽视频 | 波多野结衣在线观看一区二区三区 | 色婷婷导航 | 在线看中文字幕 | 日日躁天天躁 | 国产精品久久一卡二卡 | 欧美日韩电影在线播放 | 日韩av一区二区在线 | 色在线国产 | 国产精品久久久久久久妇 | 日韩专区 在线 | 欧美精品国产精品 | 成人黄色小说在线观看 | 亚洲第一av在线播放 | 国产在线传媒 | 久久久av免费 | av电影免费在线看 | 国产不卡片 | 成人h在线播放 | 亚洲精品视频二区 | 最新超碰在线 | 91av在线免费看 | 久久免费视频观看 | 毛片一区二区 | 99热九九这里只有精品10 | 精品国内自产拍在线观看视频 | 久久精品99国产精品酒店日本 | 久久精品视频在线播放 | 国产成人亚洲精品自产在线 | 四季av综合网站 | 最新黄色av网址 | 久久成年人 | 天天干夜夜干 | 精品视频免费 | 四虎免费在线观看视频 | 中日韩男男gay无套 日韩精品一区二区三区高清免费 | 午夜影视剧场 | 国产精品1000| 三三级黄色片之日韩 | 婷婷射五月| 一级黄色片网站 | 免费电影播放 | 亚州激情视频 | 狠狠久久婷婷 | 亚洲精品看片 | 99免费看片| 色姑娘综合 | 五月天婷亚洲天综合网鲁鲁鲁 | 国产成人福利片 | 91视频中文字幕 | 久久综合九色99 | 婷婷激情欧美 | 97超碰国产精品女人人人爽 | 色偷偷88欧美精品久久久 | 成人综合婷婷国产精品久久免费 | 在线免费观看黄色 | 91视视频在线直接观看在线看网页在线看 | www.狠狠色.com | 美女视频黄是免费的 | 久热av | 中文字幕日本在线观看 | 国产亚洲情侣一区二区无 | 精品一区二区6 | 人人干在线 | 在线欧美日韩 | av福利在线| 免费亚洲片| 久久 精品一区 | 蜜臀aⅴ国产精品久久久国产 | 一级片色播影院 | 天天艹天天干天天 | 国产伦理剧 | 亚洲欧洲av| 99爱这里只有精品 | 999热线在线观看 | 精品一区精品二区高清 | 91成版人在线观看入口 | 亚洲一级片在线观看 | 日韩在线观看网站 | 成人97人人超碰人人99 | 91污视频在线观看 | 香蕉在线播放 | 国产毛片久久久 | 在线免费观看国产黄色 | 97超碰人人| 国产中文在线播放 | 伊人婷婷在线 | 人人澡超碰碰97碰碰碰软件 | 国产美女免费视频 | 在线观看www. | jizz欧美性9 国产一区高清在线观看 | 国产精品国内免费一区二区三区 | 中文字幕丝袜美腿 | 国产二区免费视频 | 久久大片网站 | 日韩视频图片 | 日韩色在线观看 | 成人影片免费 | 91日韩国产 | 国产91免费观看 | 激情电影在线观看 | 好看av在线 | 蜜臀av在线一区二区三区 | 麻豆手机在线 | 欧美高清成人 | 日韩在线视频看看 | 日韩在线字幕 | 精品国精品自拍自在线 | 婷婷5月色 | 久久伊99综合婷婷久久伊 | 亚洲精品视频在线免费 | 免费看黄的视频 | 激情综合狠狠 | 中文字幕91在线 | 精品一区电影国产 | 国产亚洲精品久久久久久无几年桃 | 免费成人av | 国产在线精品福利 | 又色又爽又激情的59视频 | 国产日韩欧美在线观看 | 99精品视频在线观看播放 | 国产在线观看免费 | 免费99精品国产自在在线 | 国产做aⅴ在线视频播放 | 天天干天天干天天操 | 91精品国产99久久久久久久 | 亚洲精品小视频 | av免费成人 | 在线播放一区 | 九色在线| 久草在线视频国产 | 欧美一级电影免费观看 | 中文字幕精 | 国产精品久久久久久久久久久久午 | av理论电影 | 99综合影院在线 | 国产亚洲精品福利 | 成人h动漫精品一区二 | 97超碰人人模人人人爽人人爱 | 免费国产一区二区 | 久草在线99 | 精品成人a区在线观看 | 久久66热这里只有精品 | 国产一区免费视频 | 99久热精品 | 国产毛片久久久 | 精品影院一区二区久久久 | 99久久免费看 | 亚洲精品国产麻豆 | www.888.av | 亚洲 欧洲 国产 日本 综合 | 一级黄色片网站 | 中字幕视频在线永久在线观看免费 | 91精品国产99久久久久 | 国产精品久久久电影 | 国产毛片久久久 | 国产成人黄色网址 | 久久99亚洲热视 | www免费网站在线观看 | 91精品亚洲影视在线观看 | 亚洲精品字幕在线观看 | 中文区中文字幕免费看 | 国产在线欧美 | 免费看的黄色的网站 | 500部大龄熟乱视频使用方法 | 欧美精品一区二区蜜臀亚洲 | 精品国产不卡 | a天堂最新版中文在线地址 久久99久久精品国产 | 91精品综合在线观看 | 天天色天天骑天天射 | 亚州免费视频 | 中文字幕在线视频免费播放 | 天天操夜夜曰 | 国产伦精品一区二区三区在线 | 亚洲视频电影在线 | 日韩欧美国产精品 | 成人av免费 | 成人a视频| 欧美最爽乱淫视频播放 | 成人午夜黄色影院 | 亚洲人精品午夜 | 亚洲欧美日韩国产一区二区三区 | 国产精品第二页 | 国产91精品久久久久久 | 亚洲国产日韩一区 | 色噜噜在线观看视频 | 伊人婷婷色 | 狠狠操综合网 | 骄小bbw搡bbbb揉bbbb | www.狠狠色.com | 国产精品99久久久久久久久久久久 | 亚洲播放一区 | 亚洲一区二区高潮无套美女 | www国产精品com| 开心丁香婷婷深爱五月 | 首页中文字幕 | 欧美国产精品一区二区 | 人人爱在线视频 | 国产在线一线 | 精品一区二区免费 | 国产一卡在线 | 麻豆一区二区三区视频 | 97色资源 | 婷婷久久综合九色综合 | 丝袜+亚洲+另类+欧美+变态 | 五月婷婷丁香色 | 国产大片黄色 | 91手机视频 | 亚洲国产日韩欧美 | 国产精品久久久久久久久免费看 | 麻豆影视网 | 久久精品一二区 | 久草精品在线观看 | 中文字幕在线日 | 欧美激情视频一区二区三区 | 97精品欧美91久久久久久 | 99热免费在线 | 久久激情视频免费观看 | 国产午夜三级一区二区三桃花影视 | 麻豆国产精品永久免费视频 | 亚洲精品国产精品国自产观看浪潮 | 狠狠干夜夜操天天爽 | 国产成人精品一区二区在线观看 | 天天操夜夜叫 | 色瓜| 亚洲观看黄色网 | 在线看岛国av | 粉嫩av一区二区三区四区在线观看 | 午夜.dj高清免费观看视频 | 日韩精品一区二区三区免费视频观看 | 国产中年夫妇高潮精品视频 | 激情综合电影网 | 日韩理论电影在线观看 | 国产一级免费在线 | 国内精品久久久久久久久久 | 精品国偷自产国产一区 | 中文字幕一区二区三区久久蜜桃 | 国产精品美女久久久久久久 | 日韩欧美一区二区三区黑寡妇 | 夜夜夜| 亚洲精品成人网 | 免费视频 你懂的 | 亚州精品在线视频 | 国内少妇自拍视频一区 | 成 人 免费 黄 色 视频 | 欧美精品久久人人躁人人爽 | 99在线精品视频观看 | 蜜臀av.com | 中文字幕在线网址 | 国产精品入口麻豆 | 国产麻豆视频免费观看 | 免费在线视频一区二区 | 亚洲精品理论 | 成人亚洲免费 | 中文国产在线观看 | 欧美激情视频在线观看免费 | 国产激情久久久 | 人人艹视频 | 欧美日韩99 | 亚洲电影网站 | 天天操天天操天天爽 | 黄色app网站在线观看 | 久久色视频| 久久综合综合久久综合 | 狠狠的干狠狠的操 | 日韩网站在线 | 黄色a一级视频 | 色视频网址 | 激情欧美一区二区三区免费看 | 国产精品久久久久久69 | 欧美亚洲一区二区在线 | 日韩欧美视频免费在线观看 | 中午字幕在线 | 日韩av在线看 | 色视频网页 | 日本三级在线观看中文字 | 美女福利视频在线 | 热精品 | 天天躁日日躁狠狠躁av麻豆 | 亚洲片在线观看 | 黄色a在线| 麻豆av一区二区三区在线观看 | 国产午夜精品理论片在线 | 亚洲精品午夜久久久 | 免费av网站在线 | 免费精品国产va自在自线 | 久久久一本精品99久久精品66 | 亚洲精品欧美视频 | 天天摸天天干天天操天天射 | 黄网站色视频 | 亚洲国产中文字幕在线视频综合 | 96久久久 | 久久精品一区二区三 | 中文字幕日本在线 | 国产三级精品三级在线观看 | 国产综合香蕉五月婷在线 | 国产 在线 高清 精品 | 亚洲日韩欧美视频 | 日韩精品一区二区在线观看视频 | 婷婷四房综合激情五月 | 久久伦理电影网 | 欧美激情综合五月色丁香小说 | 99九九热只有国产精品 | 久草视频在线播放 | 国产香蕉久久精品综合网 | 国产aa免费视频 | 日韩电影在线观看一区二区 | 色视频在线免费观看 | 久久久免费在线观看 | 亚洲欧美日韩在线一区二区 | 亚洲精品一区中文字幕乱码 | 中文字幕日韩国产 | 天天舔天天搞 | 久日精品 | 国产剧情av在线播放 | 国产色视频一区二区三区qq号 | 国产日韩中文字幕 |