日韩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)容還不錯,歡迎將生活随笔推薦給好友。

    日韩在线免费视频 | 日韩欧美国产精品 | 欧美一级性生活 | 最新av观看| 麻豆传媒一区二区 | www.天天草 | 亚洲视频播放 | 99视频免费观看 | 亚洲国产精品va在线 | 国产原创91 | 精品一区二区av | 亚洲一区二区视频 | 中文字幕高清在线播放 | 天天天天爱天天躁 | 免费视频 三区 | 日韩在线大片 | 日韩在线网址 | 国产亚洲一区二区在线观看 | 亚洲v欧美v国产v在线观看 | 91色影院 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 日韩视频欧美视频 | 成人a视频在线观看 | 精品字幕在线 | 日韩欧美国产免费播放 | 日本精品视频网站 | 午夜婷婷网| 国产精品嫩草影院123 | 国产一区国产二区在线观看 | 黄色一级免费 | 欧美一区二区免费在线观看 | 日日爱视频 | 亚洲精品一区中文字幕乱码 | 久久久久色 | 亚洲精选99 | 天天干天天草 | 国产一区在线播放 | 日韩欧美在线视频一区二区 | 欧美在线一级片 | 91精品国产乱码 | 9草在线 | 国产在线精品福利 | 日日天天av | 欧美做受高潮电影o | 99高清视频有精品视频 | 欧美91视频| 国产一区二区日本 | 亚洲毛片一区二区三区 | 国产黄色片免费 | 国产精品21区 | 超碰在线观看97 | 色www永久免费 | 一级黄色大片在线观看 | 亚洲国产日韩一区 | 91精品电影| 69av久久| aav在线 | 久久久久五月 | 亚洲一级免费电影 | 91中文在线 | 久久成年人 | 欧美成年黄网站色视频 | 免费a v观看 | 毛片精品免费在线观看 | 国产va精品免费观看 | 日韩特级黄色片 | 青春草免费在线视频 | 久久99操 | 亚洲欧美视频一区二区三区 | 精品福利在线 | 中文字幕一区二区三区在线播放 | 人人爽人人爽人人 | 中文日韩在线 | 最近更新好看的中文字幕 | 国产成人a v电影 | 免费能看的av | 亚洲毛片在线观看. | 不卡的av中文字幕 | av大全在线观看 | 精品久久久久久久久久久院品网 | 日韩免费观看av | 国产精品久久久久永久免费看 | 9在线观看免费高清完整版在线观看明 | 在线免费91 | 国产专区在线 | 日韩精品视频在线免费观看 | 国产精品乱码一区二区视频 | 亚洲欧美日本国产 | 在线不卡中文字幕播放 | 玖玖在线播放 | 丝袜美腿在线 | 2022久久国产露脸精品国产 | 国产精品门事件 | 粉嫩一区二区三区粉嫩91 | 国内精品亚洲 | 性色av免费看 | 久久免费在线观看视频 | 久久久免费高清视频 | 亚洲免费在线看 | 久久精品视频观看 | 久久成人国产 | 亚洲国产视频a | 免费在线一区二区 | 国产精品夜夜夜一区二区三区尤 | 久久亚洲精品国产亚洲老地址 | 国产精品美女久久久久久久 | 国产一区二区视频在线 | 午夜av一区二区三区 | 成人一区二区三区中文字幕 | 黄色片视频在线观看 | 91大神在线看| 国产精品入口传媒 | 免费精品 | 亚洲一区二区精品视频 | 久久久精品小视频 | 91天天操| av在线免费在线观看 | 视色网站| 精品理论片| 99精品热 | 欧美中文字幕久久 | 精品国产一区二区三区久久久久久 | 免费三级a | 在线视频日韩精品 | 视频在线观看入口黄最新永久免费国产 | 国产无套一区二区三区久久 | 国产精品日韩高清 | 91精品国产一区二区在线观看 | 黄色三级免费片 | 国产精品精品国产色婷婷 | 国产精品久久久久久久久久不蜜月 | 色99之美女主播在线视频 | 国偷自产视频一区二区久 | 成人av电影免费在线播放 | 成人av一区二区在线观看 | 久久久久久久久久国产精品 | 五月婷婷六月综合 | 免费高清在线观看成人 | 在线播放av网址 | 午夜精品一区二区三区在线播放 | 亚洲黄色av | 九九热免费观看 | 亚洲男女精品 | 国产精品 国产精品 | 日韩视频在线观看视频 | 亚洲九九九在线观看 | 亚洲国产精品va在线看黑人 | 波多野结衣精品在线 | 久久久久久久久影视 | 一区二区三区四区在线免费观看 | 三级黄色理论片 | 久久久久免费精品视频 | 九色精品免费永久在线 | 嫩草伊人久久精品少妇av | 亚洲美女精品 | 欧美一区二区三区激情视频 | 亚洲免费精品视频 | 在线观看av大片 | 日日夜夜国产 | 国产精品久久久久久69 | 精品免费久久久久久 | 亚洲另类在线视频 | 五月天婷婷在线视频 | 99久久99久久精品免费 | 特级aaa毛片 | 91福利免费 | 在线观看亚洲成人 | 国产无套视频 | 手机av看片 | 久久综合综合久久综合 | 亚洲国产三级在线 | 久草久| 国产一二三四在线视频 | 久久久久伦理电影 | 三级黄色在线观看 | 中文字幕在线观看第一页 | 最近日本字幕mv免费观看在线 | 久久精品国产一区二区电影 | 99久久久国产精品免费观看 | 国产91电影在线观看 | www.99av | 少妇bbb搡bbbb搡bbbb | 日韩色综合网 | 美女久久精品 | 99超碰在线播放 | 91入口在线观看 | 国产精品美女久久久久久久久 | 国产一区福利在线 | 免费亚洲婷婷 | 国产亚洲精品久久久网站好莱 | 男女男视频 | 国产精品福利无圣光在线一区 | 日韩成人欧美 | 91传媒在线播放 | 日韩高清一区在线 | 中文字幕国内精品 | 91在线视频观看免费 | 丁香婷婷激情啪啪 | 国产韩国日本高清视频 | 精品视频| 好看的国产精品视频 | 国产精品一区电影 | 久久精品综合视频 | 国产精品一区二区三区观看 | 天天干,天天射,天天操,天天摸 | 日韩电影久久 | 国产精品午夜免费福利视频 | 黄色精品国产 | 男女拍拍免费视频 | 99视频网站 | 国产五月天婷婷 | 色婷婷色 | 在线视频一二区 | 91成年视频| 久久综合九色综合欧美狠狠 | 国产一区欧美日韩 | 园产精品久久久久久久7电影 | 午夜 免费 | 五月亚洲| 国产精品久久久久久久久毛片 | 精品一二| 欧美日韩国产一区二 | 精品亚洲视频在线 | 激情偷乱人伦小说视频在线观看 | 国产成人久久精品一区二区三区 | 日韩三区在线 | 婷香五月 | 国产精品1000| 欧美日韩在线观看一区二区三区 | 日韩av影片在线观看 | 免费亚洲精品 | 久久国产一区二区三区 | 亚洲成人av电影 | 国产色视频一区 | 伊人婷婷久久 | 久草男人天堂 | 亚洲精品啊啊啊 | 国产99久久久精品视频 | 2022国产精品视频 | 丁香视频在线观看 | 欧美一二三区在线观看 | 天天爽人人爽 | 成人在线播放网站 | 精品一区91 | 在线电影 一区 | 久久精品草 | 麻豆系列在线观看 | 亚洲美女在线国产 | 一区二区三区免费在线观看视频 | 免费a v在线| 国产黄色资源 | 97超级碰| 永久免费的啪啪网站免费观看浪潮 | 成人av在线一区二区 | 久视频在线 | 狠狠躁天天躁 | 91成人网页版 | 69亚洲视频| 91在线九色 | 国产精品区一区 | 国产高清日韩 | 国产精品久久久久久久久免费看 | 成人免费观看在线视频 | 国产亚洲精品中文字幕 | 色婷婷播放 | 成人国产精品一区 | 久草www| 日韩在线视频免费播放 | 久久久久女人精品毛片九一 | 国产资源在线免费观看 | 久99久久| 五月婷社区 | 亚洲精品国产精品国产 | 999久久国产精品免费观看网站 | 亚洲精品国产高清 | 国产精品美女久久久 | 黄色软件在线观看视频 | 四虎在线免费观看 | 一级片视频在线 | 久久久久久久久久亚洲精品 | 在线探花 | av高清一区 | 玖玖玖在线观看 | 国产精彩视频一区二区 | 亚洲人在线视频 | 免费v片 | 天天爽天天爽天天爽 | 在线免费三级 | 久久国产亚洲精品 | 天天天综合网 | 国产青春久久久国产毛片 | 午夜久久电影网 | 91视频免费观看 | 国产精品k频道 | 午夜精品一区二区三区可下载 | 草久电影 | 欧美精品免费在线观看 | 国产小视频网站 | 久久久精品电影 | 亚洲区视频在线观看 | 99在线国产| 日本在线免费看 | 中文字幕在线观看一区二区 | 午夜精品久久久久99热app | 国产精品字幕 | 日韩欧美在线视频一区二区 | 久久xx视频| 在线播放国产一区二区三区 | 毛片网站在线看 | 97人人人| 日韩成人免费观看 | 免费中午字幕无吗 | 五月婷香蕉久色在线看 | 天天干天天操天天 | 午夜.dj高清免费观看视频 | 国产91探花 | 一级片视频免费观看 | 一区二区三区四区五区六区 | 97综合在线 | 91丨九色丨国产女 | 亚洲精品资源在线 | 成人久久久久 | 一区二区三区免费在线播放 | 久久久久电影网站 | 在线视频 国产 日韩 | 久草在线久 | 午夜少妇一区二区三区 | 成人免费共享视频 | 久久国产午夜精品理论片最新版本 | 亚洲欧美一区二区三区孕妇写真 | 日韩av成人免费看 | 久久久精品亚洲 | 国产精品网站 | 免费在线观看国产精品 | 免费观看成人 | 黄网站大全 | 久久久久亚洲国产精品 | 97网| 日韩亚洲国产中文字幕 | 久久久影视 | 亚洲国产精品视频 | 国产免费av一区二区三区 | 91成人精品一区在线播放 | 成人手机在线视频 | 五月激情丁香婷婷 | www.com久久 | 国产视频在线观看一区 | 超级碰碰碰视频 | 亚洲高清在线视频 | 五月综合激情 | 日韩精品观看 | 亚洲国产精品视频在线观看 | 欧美在线18 | 亚洲aⅴ一区二区三区 | 久久国产精品偷 | 丁香在线视频 | 手机av永久免费 | 亚av在线| 亚洲少妇xxxx | 亚洲国产操 | www狠狠操 | 久久国内免费视频 | 国产999 | 国产高清在线 | 99国内精品 | 波多野结衣精品视频 | 国产黄在线看 | 欧美精品久久久久久久久久丰满 | 黄色av一区二区三区 | 日韩三级av | 综合色婷婷 | 500部大龄熟乱视频使用方法 | 免费在线播放视频 | 免费黄色网址网站 | 欧美日韩高清一区二区 | 九九交易行官网 | 国产视频在线免费 | 久在线| 91chinesexxx| 久久婷婷色 | 色视频网站免费观看 | 97超碰成人在线 | 一区在线播放 | 婷婷综合伊人 | 欧美在线一 | 日韩av在线小说 | 色天天综合网 | 婷婷丁香激情五月 | 91亚洲精品视频 | 精品国产色 | 国产日韩视频在线播放 | 日日躁夜夜躁xxxxaaaa | 天天操狠狠操 | 国产高清绿奴videos | 成人三级网址 | 亚洲一级电影在线观看 | 黄色av影视 | 91桃色在线观看视频 | 美女av在线免费 | 丁香视频全集免费观看 | 国产+日韩欧美 | 婷婷四房综合激情五月 | 亚洲精品在线观看免费 | 97色综合 | 亚洲精品久久久久久中文传媒 | 九九视频精品免费 | 四虎国产精品免费观看视频优播 | 欧美日韩一级视频 | 嫩草av影院 | 97成人啪啪网 | 国产成人精品一区二三区 | 国产精品一区二区三区99 | 日韩欧美视频免费看 | 亚洲精品中文在线 | 5月丁香婷婷综合 | 婷婷久久一区 | av怡红院| 在线看v片成人 | 91精品爽啪蜜夜国产在线播放 | 中文字幕第一页在线 | 伊人国产女 | 国产精品视频专区 | 免费色视频在线 | 日韩激情小视频 | 超薄丝袜一二三区 | 99色在线观看 | 狂野欧美激情性xxxx | 国产自产高清不卡 | 国产做aⅴ在线视频播放 | 在线观看黄av | 亚洲免费av在线播放 | 色网站在线看 | 91尤物在线播放 | 国产一区欧美二区 | 国产99亚洲| 国产一区欧美日韩 | 国产成人黄色av | 久久午夜国产精品 | 午夜黄色大片 | 三级黄色欧美 | 超碰人人99| 九九在线视频免费观看 | 久久久久久国产精品 | 激情偷乱人伦小说视频在线观看 | 99福利片 | 国内精品中文字幕 | 一级性av | 欧洲一区精品 | 色噜噜狠狠狠狠色综合久不 | 在线观看aa | 91传媒在线播放 | 精品国产视频在线 | 精品国产一区二 | av在线播放中文字幕 | 狠狠色丁香婷婷综合久小说久 | 毛片.com| 丁香婷婷激情啪啪 | 狠狠操.com| 亚洲理论电影网 | 日韩电影久久 | 99久久精| 国产综合视频在线观看 | 在线精品视频免费播放 | 在线之家免费在线观看电影 | 色综合久久久网 | 久久精品视频一 | 91av资源网| 欧美-第1页-屁屁影院 | 国产超碰在线观看 | 91热视频| 国产精品入口麻豆 | 国内丰满少妇猛烈精品播 | 久久激情影院 | 国产日韩视频在线播放 | 一区二区av | 激情久久一区二区三区 | 亚洲精品成人 | 九色福利视频 | 制服丝袜在线 | 国产色道 | 欧美无极色 | 91精品免费在线 | 亚洲欧洲一区二区在线观看 | 色成人亚洲网 | 亚洲国产精品va在线看 | 欧美午夜a | 五月激情五月激情 | 又长又大又黑又粗欧美 | 六月婷色 | 日本黄网站 | 在线探花| 国产精品美乳一区二区免费 | 成人久久影院 | 丝袜制服天堂 | 在线香蕉视频 | 黄色天堂在线观看 | 日韩精品一区二区三区丰满 | av在线影视| 亚洲乱码久久 | 一区二区伦理 | 99在线精品免费视频九九视 | 中文字幕一区二区三区视频 | 免费看十八岁美女 | 中文字幕一区av | 欧美精品v国产精品 | 五月婷婷.com | 欧美一级电影免费观看 | 日韩免费观看一区二区三区 | 一区二区亚洲精品 | 毛片美女网站 | 欧美最新另类人妖 | 亚洲国产合集 | 欧美日韩91 | 日韩毛片在线免费观看 | 青青河边草免费观看完整版高清 | 亚洲日韩欧美视频 | 欧美在线观看视频一区二区三区 | 久久精品美女视频网站 | www.五月天婷婷.com | 日韩午夜大片 | 日韩精品亚洲专区在线观看 | 97在线资源 | 免费国产在线视频 | www免费黄色 | 在线观看视频福利 | 国产人成一区二区三区影院 | 国产资源免费在线观看 | 香蕉成人在线视频 | 国产免费久久av | 久久综合婷婷综合 | 免费精品国产va自在自线 | 2021国产视频 | 日韩免费视频一区二区 | 在线不卡视频 | 国产成人精品午夜在线播放 | 怡红院av久久久久久久 | 99re久久精品国产 | 日本韩国精品一区二区在线观看 | 久久国产一区 | 国产91学生粉嫩喷水 | 免费在线观看成人小视频 | 超碰在线最新网址 | 99久久激情视频 | 久久综合精品国产一区二区三区 | 91av在线视频播放 | 久99久在线 | 五月激情五月激情 | 欧美韩国日本在线观看 | 国产91粉嫩白浆在线观看 | 日韩精品中文字幕在线不卡尤物 | 国产精品久久久区三区天天噜 | 久久99国产视频 | 亚洲97在线 | 国产区精品区 | 91免费在线播放 | 色偷偷中文字幕 | 99视频精品视频高清免费 | 国产视频在线观看一区 | 日本一区二区三区视频在线播放 | 国产精品一区电影 | 欧美精品中文字幕亚洲专区 | 日韩精品黄 | 国产精品欧美久久 | 99热这里只有精品1 av中文字幕日韩 | 91精品一区二区三区蜜桃 | 人人澡超碰碰 | 91精品办公室少妇高潮对白 | 狠狠伊人| 精品久久久成人 | 99爱这里只有精品 | 亚洲第一区在线播放 | 国产一线二线三线在线观看 | 天天干天天操天天爱 | 国产综合精品一区二区三区 | 欧美一区二区在线看 | 91麻豆精品| 性色va | 免费看的黄色小视频 | 黄色一级免费电影 | 日韩免费在线看 | 99视频在线免费 | 欧美日韩国产在线精品 | 久久久国产成人 | 久久久久成人精品 | 婷婷色综合色 | 色全色在线资源网 | 超碰97.com | 国产成人精品女人久久久 | 久久人人爽人人片av | 五月宗合网 | 在线观看亚洲成人 | 亚洲精品男人天堂 | 亚洲精品国产精品国自产观看 | 91精品国产乱码久久 | 国产一区国产二区在线观看 | 亚洲狠狠 | av免费看看 | 免费黄色一区 | 日韩精品中文字幕在线观看 | 日韩精品视 | 国内视频| 国产午夜精品免费一区二区三区视频 | 亚洲国产美女久久久久 | 久久最新网址 | 国产黄色免费观看 | 一区二区三区播放 | 狂野欧美激情性xxxx欧美 | 国产又粗又猛又黄 | 成片免费观看视频999 | 狠狠操狠狠插 | 亚洲一二视频 | 国产成人久久精品 | 91九色视频观看 | 激情欧美国产 | 在线播放av网址 | 99综合电影在线视频 | 久久久久国产一区二区三区四区 | 激情开心网站 | 精品一区av | av成人在线电影 | 五月香视频在线观看 | 在线观看av网站 | 97电影在线看视频 | 操久久免费视频 | 中日韩在线 | 天天操天 | 久久这里只有精品视频99 | 天天天插| 国产精品乱码一区二三区 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 九九色视频 | 911香蕉| 久久成人国产精品一区二区 | 精品福利国产 | 九九九热精品免费视频观看 | 成年人国产精品 | 欧美国产日韩一区二区三区 | 国产特级毛片aaaaaaa高清 | 开心色插 | 成人免费观看视频大全 | 国产亚洲精品久久久久久网站 | av黄色在线播放 | 国产成人一区二 | 中文在线字幕免费观 | 狂野欧美激情性xxxx欧美 | 日韩精品中文字幕在线播放 | 亚洲国产精品va在线看黑人 | 精品天堂av| 91精品国产91久久久久福利 | 操操操av | 久久成年人视频 | 亚洲国产剧情av | 精品96久久久久久中文字幕无 | 国产精品一区二区吃奶在线观看 | 一区二区欧美激情 | av免费观看网址 | 成人久久毛片 | 免费看一级特黄a大片 | 日韩高清在线观看 | 啪啪激情网 | 最新一区二区三区 | av噜噜噜在线播放 | 人人插人人 | 天天操夜夜拍 | 成人久久久久久久久久 | 在线看v片成人 | 日本性生活一级片 | 最新国产精品亚洲 | 亚洲综合欧美精品电影 | 操碰av| 99精品欧美一区二区三区黑人哦 | 夜夜天天干| 精品人人爽 | 亚洲理论电影网 | 欧美性黑人 | 五月婷婷激情 | 三三级黄色片之日韩 | 三级黄色大片在线观看 | 五月婷婷六月综合 | 国产成人精品一区在线 | 97超碰精品 | 国内外成人在线 | 高清免费在线视频 | 成人在线观看你懂的 | 99精品视频在线观看 | 国产不卡在线看 | 色婷婷九月 | 视频在线在亚洲 | 色综合色综合色综合 | 最近中文字幕视频完整版 | 国产精品午夜久久久久久99热 | 国产99re| 久久久久9999亚洲精品 | 亚av在线| 精品乱码一区二区三四区 | 亚洲成年片 | 成年人网站免费在线观看 | 国产又粗又长又硬免费视频 | 奇米影视四色8888 | 亚洲成人精品久久久 | 亚洲精品国产第一综合99久久 | 91欧美视频网站 | 麻豆va一区二区三区久久浪 | 亚洲aⅴ久久精品 | 国产精品久久久999 国产91九色视频 | 麻豆国产在线视频 | 99精品免费久久久久久日本 | av怡红院 | 91网站观看 | 久久99精品国产99久久 | 久久久久久伊人 | 麻豆观看 | 免费看的黄色的网站 | 色多视频在线观看 | 亚洲精品999 | 色欧美日韩 | 国产一级片不卡 | 国产女v资源在线观看 | 中文字幕 国产精品 | 91精品国产91p65 | 亚洲精品国产第一综合99久久 | 亚洲精选国产 | 国产精品一区二区美女视频免费看 | 欧美日韩后 | 高清免费在线视频 | 国产成人无码AⅤ片在线观 日韩av不卡在线 | 欧美日韩国产精品一区 | 黄色网www| 日本美女xx| 97国产精品一区二区 | 亚洲成人黄色在线观看 | 婷婷在线视频 | 中文字幕色婷婷在线视频 | 天天爽天天爽天天爽 | 97激情影院 | 成人av一区二区三区 | 国产最新在线视频 | 国产在线观看高清视频 | 成人av电影免费观看 | 奇米四色影狠狠爱7777 | 日韩中文字幕第一页 | 亚洲乱码国产乱码精品天美传媒 | 成人高清av在线 | 人人精品 | 国产精品成人免费精品自在线观看 | 国产美女网站在线观看 | 国内精品久久久久久久影视简单 | 99久久99久久精品国产片 | 日韩av一区二区在线 | 久久免费国产电影 | 91在线精品一区二区 | 男女啪啪免费网站 | 中文在线a∨在线 | 91亚洲精品久久久蜜桃 | 国产精品成人久久 | 西西444www大胆无视频 | 91亚洲精品久久久蜜桃网站 | av高清在线 | 欧美一区二区三区在线观看 | 黄色av电影网| 天天操天天插 | 国产精品毛片一区视频 | 国产精品福利av | 亚洲精品影院在线观看 | 色噜噜在线观看 | 中文字幕在线看片 | 在线国产一区二区三区 | 国产精品久久久久永久免费观看 | 成人黄色影片在线 | www.xxxx欧美| 亚洲成人午夜在线 | 国产精品一区二区久久国产 | 成人黄大片视频在线观看 | 在线成人一区二区 | 一区二区三区影院 | 欧美夫妻生活视频 | 麻豆视频在线观看 | 亚洲精品乱码久久 | 99久高清在线观看视频99精品热在线观看视频 | 亚州精品一二三区 | 最近中文国产在线视频 | 日韩成人免费观看 | 免费黄色网址网站 | 丁香婷婷社区 | 免费日韩 精品中文字幕视频在线 | 亚洲欧美一区二区三区孕妇写真 | 国产亚洲视频在线免费观看 | 91久久精品一区二区三区 | 99久久精品免费看 | av电影亚洲| 久久tv视频| 亚洲国产成人久久 | 国产精品久久久久久久久久了 | 91视频在线观看大全 | 国产综合在线观看视频 | 日韩色视频在线观看 | 97国产精品久久 | 91免费视频网站在线观看 | 国产 日韩 欧美 中文 在线播放 | 99视频精品 | 91成人网在线播放 | 欧美一二三专区 | 欧美激情精品久久久久久免费 | 久草视频在线播放 | 国产在线观看h | 中文字幕一区二区三区四区久久 | 天堂av免费观看 | 一区二区三区手机在线观看 | 香蕉在线观看视频 | 91伊人久久大香线蕉蜜芽人口 | 久久影院精品 | 人人爱夜夜操 | 精品视频国产 | 国产麻豆果冻传媒在线观看 | 久久国产系列 | 免费视频a | 精品影院一区二区久久久 | 91精彩在线视频 | 国产精品手机在线观看 | 99热这里有精品 | 久久无码精品一区二区三区 | 狠狠干中文字幕 | 国产婷婷色 | 视频在线观看亚洲 | 色婷五月天| 久久精品永久免费 | 午夜国产福利在线 | 啪嗒啪嗒免费观看完整版 | 综合激情婷婷 | 精品久久国产一区 | 青青射 | a色视频 | 日韩手机在线 | 国产成人一级 | 九九免费精品视频 | 综合国产在线 | 亚洲男人天堂2018 | 瑞典xxxx性hd极品 | 日韩av在线一区二区 | 岛国片在线 | 国产99久久久欧美黑人 | 亚洲精品中文字幕在线观看 | 天天射色综合 | 天天射综合网视频 | av中文字幕网址 | 久久另类视频 | 久久久久久毛片精品免费不卡 | 亚洲最新视频在线 | 区一区二在线 | 夜夜骑首页 | 亚洲精品午夜aaa久久久 | 91在线亚洲 | 国产精品99久久久久久久久久久久 | 成人久久视频 | 免费日韩一区 | 亚洲精品www久久久久久 | 久久综合毛片 | 国产精品久久久久久久久软件 | 亚洲精品在线观看网站 | 天天做天天爱天天综合网 | 日韩电影中文,亚洲精品乱码 | 91精品中文字幕 | 亚洲成人在线免费 | 麻豆视频免费 | 日韩三级精品 | av在线专区 | 国产中文字幕在线观看 | 亚洲美女在线国产 | 国产一区在线视频 | 日韩理论片中文字幕 | 成人a大片 | 男女免费av| 成人av久久 | 欧美成人91 | 国产在线日本 | 亚洲精品小视频 | 国产精品一区二区av | 国产清纯在线 | 国产精品欧美一区二区三区不卡 | 久久这里只有精品9 | 亚洲 欧美 国产 va在线影院 | 99视频网站 | 成年人黄色免费视频 | 黄p网站在线观看 | 日韩一级片网址 | 久久国产精品影片 | 欧美一二三视频 | 国产亚州精品视频 | 亚洲精品88欧美一区二区 | 欧美在线观看视频一区二区 | 亚洲欧美日韩一二三区 | 99精品视频中文字幕 | 国产日韩精品一区二区三区在线 | 日韩精品免费专区 | 日韩丝袜视频 | 日本黄网站 | 国际精品久久久久 | 免费在线电影网址大全 | 成人试看120秒 | 黄色一级大片在线免费看国产一 | 狠狠色伊人亚洲综合网站色 | 国产成人99av超碰超爽 | 色婷婷狠狠五月综合天色拍 | 狠狠撸电影 | 午夜精品久久久 | 久久99爱视频 | 美女搞黄国产视频网站 | 国产精品久久中文字幕 | 天天舔夜夜操 | 免费日韩一区二区三区 | 成人久久久久 | www.伊人网| 99一级片 | 亚洲视频1区2区 | 亚洲黄污| .国产精品成人自产拍在线观看6 | 91女子私密保健养生少妇 | av一区二区在线观看中文字幕 | 国产日韩精品一区二区三区在线 | 国产99亚洲| 韩国中文三级 | 亚洲欧美日韩不卡 | 91在线日韩 | 久草视频国产 | 九九热免费视频在线观看 | 免费色视频 | 亚洲黄在线观看 | 中文字幕一区在线观看视频 | 日韩超碰在线 | 久草干 | 久久夜色网 | 349k.cc看片app| 天天操天天操天天操天天操 | 国产第一页在线观看 | 西西4444www大胆无视频 | 日韩在线欧美在线 | 四虎国产免费 | 国产精品免费人成网站 | 久久黄色网页 | 国产小视频网站 | 国产精品成人久久久久久久 | 亚洲狠狠丁香婷婷综合久久久 | 亚洲一级电影视频 | 国产精品一二 | 91人人揉日日捏人人看 | 波多野结衣一区二区三区中文字幕 | 亚洲欧美日韩精品一区二区 | 欧美福利精品 | 中文字幕在线观看你懂的 | 日日草天天草 | 中文国产字幕在线观看 | 久久艹在线观看 | 波多野结衣亚洲一区二区 | 久久精品韩国 | 亚洲精品国产成人av在线 | 97免费在线观看 | 91九色蝌蚪在线 | 免费视频久久久久久久 | 97免费在线观看视频 | www日韩欧美 | 欧美一级性生活片 | 天天射射天天 | 成人a视频在线观看 | 亚洲高清在线精品 | 久久伦理 | 国产一区二区精品久久91 | 黄色大片日本免费大片 | 天天天干天天天操 | 精品国产伦一区二区三区观看方式 | 日韩欧美精品一区二区三区经典 | 中文超碰字幕 | 欧美日本不卡高清 | 中文字幕精品三级久久久 | 免费观看av| 日韩av中文字幕在线 | 日本99热| 制服丝袜在线 | 三上悠亚一区二区在线观看 | 中文字幕美女免费在线 | 欧美aa一级 | 在线日本看片免费人成视久网 | 精品一区二区三区四区在线 | 韩国av一区二区三区在线观看 | 久久精品久久久久久久 | 亚洲综合色视频在线观看 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 免费看国产一级片 | 午夜精品999 | 日韩黄色av网站 | 天天操天天色综合 | 九九热在线视频免费观看 | 性色av免费在线观看 | 在线观看黄色大片 | 亚洲成av人电影 | 免费99精品国产自在在线 | 黄色小说免费在线观看 | 国产视频一| 久久69精品 |