JAVA面試208道實用題,答案持續更新整理。

一、JAVA基礎

1. JDK JRE 有什麼區別?

JRE(java Runtime Environment)是java運行時環境,包含了java虛擬機,java基礎類庫,是java語言編寫的程序運行時所需要的軟件環境,是提供給想運行java程序的用戶使用的。

JDK(java Development kit)時java開發工具包,是程序員使用java語言編寫java程序所需的開發工具包,是提供給程序員使用的。JDK包含JRE,同時還包含了編譯java源碼的編譯器javac,還包含了很多java程序調試和分析的工具:jconsole,jvisualvm等工具,還包含了java程序編寫所需要的文檔和demo例子程序。

2. == equals 的區別是什麼?

==比較 的是變量(棧區)內存中存放的對象的(堆區)內存地址,用來判斷兩個對象地址是否相同,即是否指向相同一個對象。比較的是真正意義上的指針操作。

  比較的是操作符兩端的操作數是否是同一個對象;

equals用來比較的是兩個對象的內容是否相等,由於所有的類都是繼承自java.lang.object類,所以適用與所有對象,如果沒有對該方法進行覆蓋,Object中的equals方法等同==

public boolean equals(Object obj) {

    return (this == obj);

}

"=="比"equals"運行速度快,因爲"=="只是比較引用。

3. 兩個對象的 hashCode()相同,則 equals()也一定爲 true,對嗎?

不一定相同,equals成立的時候hascode不一定相同,除非重寫equalss和hashcode方法

兩個對象==,其哈希碼一定相等;

String類已經重寫equals、hashCode方法,所以兩個String對象equals相等時,它們的哈希碼是一定相等的;

4. final Java 中有什麼作用

final可以修飾類、函數、變量,即通常用來修飾你不希望被改變的東西,最常見的就是數學函數和常數

修飾類時:爲最終類,任何類不能繼承它

修飾函數:爲最終方法,繼承它的方法不能去重寫它

修飾變量:終態變量,一旦初始化不能改變值

5. Java 中的 Math.round(-1.5) 等於多少?

Math.round()的原理是對傳入的參數+0.5之後,再向下取整返回long型,即取比它小的第一個整數或者和它相等的整數。-1

6. String 屬於基礎的數據類型嗎?

不是,基礎數據類型:數值型byte short int long 浮點型 float double 字符型 char 布爾型 Boolean,String是一個對象,是java等編程語言的字符串

7. Java 中操作字符串都有哪些類?它們之間有什麼區別?

String StringBuffer StringBuilder

String是不可變的對象,對每次String類型的改變都會生成一個新的對象,StringBufer和StringBuilder是可以改變對象的

效率:操作效率StringBuilder》Stringbuffer》String

線程安全:StringBuffer是線程安全,用於多線程,Stringbuilder是非線程安全,用於單線程

         不頻繁的字符串操作使用String,反之,Stringbuffer和Stringbuilder都優於String

線程安全是多線程編程時的計算機程序代碼中的一個概念。

在擁有共享數據的多條線程並行執行的程序中,線程安全的代碼會通過同步機制保證各個線程都可以正常且正確的執行,不會出現數據污染等意外情況。

線程安全問題大多是由全局變量靜態變量引起的,局部變量逃逸也可能導致線程安全問題。若每個線程中對全局變量、靜態變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時執行寫操作,一般都需要考慮線程同步,否則的話就可能影響線程安全。

8. String str="i" String str=new String(i)一樣嗎?

不一樣,非一個對象

9. 如何將字符串反轉?
 

public class main{

         public static void main(string[] args){

                   String s1 =’addfdfd;

                   System.out.println(new StringBuilder(s1).reverse().toString())

}

}

public class main{

public static void main(String[] args){

         string s =’5465’;

         String [] s1 = s.split(“”);

         List<String > list  = Arrays.asList(s1);

Collections.reverse(list);

system.out.println(list);

}


}

10. String 類的常用方法都有那些?

equals():字符串比較

indexOf():返回指定索引處的字符,-1

replace():替換

trim():去除字符串兩端空白

split():分割爲數組

getBytes():返回字符串的byte類型數組

toLowerCase():將字符串變爲小寫字母

toUpperCase():轉爲大寫

substring():截取

 

11. 抽象類必須要有抽象方法嗎?

不需要,抽象類不一定非要有抽象方法

abstract class cat{

         public static void sayHi(){

                   system.out.println(12);

}

}

但是即使這個類中沒有抽象方法,它也不能實例化,即不能直接構造一個該類的對象,如果一個類中有了一個抽象 方法,那麼這個類必須聲明爲抽象類,否則編譯通不過

 

12. 普通類和抽象類有哪些區別?

普通類不能包含抽象方法,抽象類可以包含抽象方法

抽象類不能直接實例化,普通類可以直接實例化

 

13. 抽象類能使用 final 修飾嗎?

不能,定義抽象類就是讓其他類繼承的,如果定義爲final該類就不能被繼承,彼此矛盾,所以final不能修飾抽象類,編輯器會提示錯誤:illegal combination of modifiers:‘abstract’and ‘final

 

14. 接口和抽象類有什麼區別?

實現:抽象類的子類用extends來繼承,接口必須使用implements來實現接口

構造函數:抽象類可以有構造函數,接口不能有

main方法:抽象類可以有main方法,並且能運行,接口不能有main方法

實現數量:類可以實現很多個接口,但是隻能繼承一個抽象類

訪問修飾符:接口中的方法默認使用public修飾,抽象類中的方法可以任意訪問修飾符

 

 

15. Java IO 流分爲幾種?

按功能:輸入流 輸出流

按類型:字節流和字符流

字節流和字符流的區別是:字節流按8位傳輸以字節爲單位輸入輸出數據,字符流按16位傳輸以字符爲單位輸入輸出數據

 

16. BIONIOAIO 有什麼區別?

BIO:Block IO同步阻塞式IO,傳統IO,模式簡單,併發處理能力低

NIO:New IO同步非阻塞IO,是傳統IO的升級,客戶端和服務器端通過Channel通道通訊,實現了多路複用

AIO:Asynchronous IO,NIO的升級,也叫NIO2

,實現了異步非堵塞IO,異步IO的操作基於事件和回調機制

17. Files的常用方法都有哪些?

Files.exists();檢測文件路徑是否存在

Files.createFile(;創建文件

Files.createDirectory();創建文件夾

Files.delete() 刪除文件或者目錄

Files.copy()

Files.move()

Files.size()

Files.read()

Files.write()

 

二、容器

18. Java 容器都有哪些?

Java容器類庫定義了兩個不同概念的容器,Collection 和 Map。

Collection:

         一個獨立元素的序列,這些元素都服從一條或者多頭規則。其中List必須按照插入的順序保存元素,set不能有重複的元素,List和Set繼承collection接口

         collection接口常用方法:

Map:

19. Collection Collections 有什麼區別?

         collection是java.util下的接口,各種集合結構的父接口, Collection接口的意義是爲各種具體的集合提供了最大化的統一操作方式。

collections是java.util下的類,包含有各種集合操作的靜態方法

20. ListSetMap 之間的區別是什麼?

LIST和set繼承自collection,Map是一個接口

List

可以允許重複的對象

可以插入多個null元素

List是一個有序容器,保持了每個元素的插入順序,輸出的順序就是插入的順序

常用的實現類有ArrayList,linkedList、vector,其中ArrayList最爲流行,它提供了使用索引的隨意訪問,LinkedList則對於經常需要從list中添加刪除的場合更爲合適

 

Set

不允許重複

只可以插入一個null元素

是一個無序容器,無法保證每個元素的存儲順序,Treeset通過Comparator或者Comparable維護了一個排序順序

Set接口最流行的幾個實現類是HashSet,linkedHashSet、TreeSet。最爲流行的是基於HashMap實現的HashSet,TreeSet還實現了SortedSet接口,因此TreeSet是一個根據compare()和compareTo()的定義進行排序的有序容器

 

 

Map

Map不是collection的子接口或者實現類,Map是一個接口

Map的每個Entry都持有兩個對象,也就是一個鍵一個值,Map可能會持有相同的值對象但鍵對象必須是唯一的

TreeMap也通過Comparator或者Comparable維護一個排序順序

Map裏你可以隨意擁有多個null值但是只能有一個null

Map流行的幾個實現類HashMap、LinkedHashMap、HashTable和TreeMap

 

21. HashMap Hashtable 有什麼區別?

主要區別線程安全性、同步性、速度

線程安全性:HashTable是線程安全的,HashMap是線程不安全的

HashTable實現線程安全的方式是修改數據時      鎖住整個HashTable,效率低,ConcurrentHashMap做了相關優化。

HashTable底層數組+鏈表實現,無論key還是value都不能爲null,初始size = 11,擴容:newsie

= oldsize*2+1

HashMap可以存儲null建和null值,線程不安全,初始size爲16,擴容newsize = oldSIze*2,size爲2的n次冪

同步:Hashtable是線程安全的,它的方法是同步的,可以直接用在多線程環境中。而HashMap則不是線程安全的,在多線程環境中,需要手動實現同步機制。

HashMap可以通過下面的語句進行同步:
Map m = Collections.synchronizeMap(hashMap);

速度:由於Hashtable是線程安全的也是synchronized,所以在單線程環境下它比HashMap要慢。如果你不需要同步,只需要單一線程,那麼使用HashMap性能要好過Hashtable。

 

22. 如何決定使用 HashMap 還是 TreeMap

TreeMap<K,V>的Key值是要求實現java.lang.Comparable,所以迭代的時候TreeMap默認是按照Key值升序排序的;TreeMap的實現也是基於紅黑樹結構。

而HashMap<K,V>的Key值實現散列hashCode(),分佈是散列的均勻的,不支持排序;數據結構主要是桶(數組),鏈表或紅黑樹。

大多情況下HashMap有更好的性能,所以大多不需要排序的時候我們會使用HashMap.

 

23. 說一下 HashMap 的實現原理?

   HashMap由數據和鏈表組成,數組是hashmap的主體,鏈表主要是解決哈希衝突而存在的,如果定位到的數組位置不含鏈表,那麼對於查找,添加等操作很快,僅需一次尋址即可;如果定位到的數組包含鏈表,對於添加操作,其時間複雜度爲o,首先遍歷鏈表,存在即覆蓋;對於查找操作來講,還需遍歷鏈表,然後通過key對象的equals方法逐一比對查找。所以,性能考慮,HashMAp中的鏈表出現越少,性能纔會越好。

https://www.cnblogs.com/xiarongjin/p/8310011.html

24. 說一下 HashSet 的實現原理?

HashSet實際上是一個HashMap實例,都是一個存放鏈表的數組。它不保證存儲元素的迭代順序;此類允許使用null元素。HashSet中不允許有重複元素,這是因爲HashSet是基於HashMap實現的,HashSet中的元素都存放在HashMap的key上面,而value中的值都是統一的一個固定對象private static final Object PRESENT = new Object();

HashSet中add方法調用的是底層HashMap中的put()方法,而如果是在HashMap中調用put,首先會判斷key是否存在,如果key存在則修改value值,如果key不存在這插入這個key-value。而在set中,因爲value值沒有用,也就不存在修改value值的說法,因此往HashSet中添加元素,首先判斷元素(也就是key)是否存在,如果不存在這插入,如果存在着不插入,這樣HashSet中就不存在重複值。

 所以判斷key是否存在就要重寫元素的類的equals()和hashCode()方法,當向Set中添加對象時,首先調用此對象所在類的hashCode()方法,計算次對象的哈希值,此哈希值決定了此對象在Set中存放的位置;若此位置沒有被存儲對象則直接存儲,若已有對象則通過對象所在類的equals()比較兩個對象是否相同,相同則不能被添加。

   iterator:返回對此set中元素進行迭代的迭代器
     size:返回此set中元素的數量(set的容量)
     isEmpty:判斷Hashset集合是否爲空
     contains:判斷某個元素是否存在於HashSet中
     add():如果此set中尚未包含指定元素,則添加指定元素

https://blog.csdn.net/qq_41026809/article/details/90449073

25. ArrayList LinkedList 的區別是什麼?

     ArrayList使用了數組的實現,封裝了對內部數組的操作
     linkedList使用了循環雙向鏈表數據結構

26. 如何實現數組和 List 之間的轉換?

List轉數組:toArray(arraylist.size()方法

List<String> arrayList = new ArrayList<String>();

 arrayList.add("s");

  arrayList.add("e");

  arrayList.add("n");

  /**

   * ArrayList轉數組

   */

  int size=arrayList.size();

  String[] a = arrayList.toArray(new String[size]);



/**

 * 數組轉list

 */

List<String> list=Arrays.asList(a);/**

  * list轉Arraylist

*/

 List<String> arrayList2 = new ArrayList<String>();

 arrayList2.addAll(list);

 System.out.println(list);

27. ArrayList Vector 的區別是什麼?

1)  Vector的方法都是同步的(Synchronized),是線程安全的(thread-safe),而ArrayList的方法不是,由於線程的同步必然要影響性能,因此,ArrayList的性能比Vector好。
2) 當Vector或ArrayList中的元素超過它的初始大小時,Vector會將它的容量翻倍,而ArrayList只增加50%的大小,這樣,ArrayList就有利於節約內存空間。

28. Array ArrayList 有何區別?

Array可以包含基本類型和對象類型,ArrayList只能包含對象類型。

Array大小是固定的,ArrayList的大小是動態變化的。

ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。

對於基本類型數據,集合使用自動裝箱來減少編碼工作量。但是,當處理固定大小的基本數據類型的時候,這種方式相對比較慢。

 

29. Queue poll() remove()有什麼區別?

remove() 和 poll() 方法都是從隊列中刪除第一個元素。如果隊列元素爲空,調用remove() 的行爲與 Collection 接口的版本相似會拋出異常,但是新的 poll() 方法在用空集合調用時只是返回 null。因此新的方法更適合容易出現異常條件的情況。

add()offer()區別:

add()和offer()都是向隊列中添加一個元素。一些隊列有大小限制,因此如果想在一個滿的隊列中加入一個新項,調用 add() 方法就會拋出一個 unchecked 異常,而調用 offer() 方法會返回 false。因此就可以在程序中進行有效的判斷!

 

 

30. 哪些集合類是線程安全的?

Vector:就比Arraylist多了個同步化機制(線程安全)。

Hashtable:就比Hashmap多了個線程安全。

ConcurrentHashMap:是一種高效但是線程安全的集合。

Stack:棧,也是線程安全的,繼承於Vector

 

31. 迭代器 Iterator 是什麼?

https://blog.csdn.net/chenssy/article/details/37521461

對 Collection 進行迭代的類,稱其爲迭代器。迭代其實我們可以簡單地理解爲遍歷,是一個標準化遍歷各類容器裏面的所有對象的方法類,它是一個很典型的設計模式。Iterator模式是用於遍歷集合類的標準訪問方法。它可以把訪問邏輯從不同類型的集合類中抽象出來,從而避免向客戶端暴露集合的內部結構。

32. Iterator 怎麼使用?有什麼特點?

Iterator iterator = list.iterator();

        while(iterator.hasNext()){

            String string = iterator.next();

            //do something

        }

hasNext():如果迭代器指向位置後面還有元素,則返回 true,否則返回false

next():返回集合中Iterator指向位置後面的元素

remove():刪除集合中Iterator指向位置後面的元素

 

33. Iterator ListIterator 有什麼區別?

Iterator迭代器包含的方法有:

hasNext():如果迭代器指向位置後面還有元素,則返回 true,否則返回false

next():返回集合中Iterator指向位置後面的元素

remove():刪除集合中Iterator指向位置後面的元素

ListIterator迭代器包含的方法有:

add(E e): 將指定的元素插入列表,插入位置爲迭代器當前位置之前

hasNext():以正向遍歷列表時,如果列表迭代器後面還有元素,則返回 true,否則返回false

hasPrevious():如果以逆向遍歷列表,列表迭代器前面還有元素,則返回 true,否則返回false

next():返回列表中ListIterator指向位置後面的元素

nextIndex():返回列表中ListIterator所需位置後面元素的索引

previous():返回列表中ListIterator指向位置前面的元素

previousIndex():返回列表中ListIterator所需位置前面元素的索引

remove():從列表中刪除next()或previous()返回的最後一個元素(有點拗口,意思就是對迭代器使用hasNext()方法時,刪除ListIterator指向位置後面的元素;當對迭代器使用hasPrevious()方法時,刪除ListIterator指向位置前面的元素)

set(E e):從列表中將next()或previous()返回的最後一個元素返回的最後一個元素更改爲指定元素e

一.相同點

都是迭代器,當需要對集合中元素進行遍歷不需要干涉其遍歷過程時,這兩種迭代器都可以使用。

二.不同點

1.使用範圍不同,Iterator可以應用於所有的集合,Set、List和Map和這些集合的子類型。而ListIterator只能用於List及其子類型。

2.ListIterator有add方法,可以向List中添加對象,而Iterator不能。

3.ListIterator和Iterator都有hasNext()和next()方法,可以實現順序向後遍歷,但是ListIterator有hasPrevious()和previous()方法,可以實現逆向(順序向前)遍歷。Iterator不可以。

4.ListIterator可以定位當前索引的位置,nextIndex()和previousIndex()可以實現。Iterator沒有此功能。

5.都可實現刪除操作,但是ListIterator可以實現對象的修改,set()方法可以實現。Iterator僅能遍歷,不能修改。

 

34. 怎麼確保一個集合不能被修改?

將參數中的List返回一個不可修改的List

Collections的靜態方法unmodifiableList可以達到目的。方法原型爲:public static <T> List<T> unmodifiableList(List<? extends T> list);用法也很簡單,傳入一個List實例la,返回這個list的只讀視圖lb,類型依然是List。之後對lb進行add、remove等改變其內容的操作將導致編譯不通過。

https://blog.csdn.net/cilen/article/details/7744969

Student1類,僅對外提供的getCourses()方法,而沒有setCourses()方法,而且

通過getCourses()方法獲得的courses是“只讀的”,如果你試圖向其添加一個新課程,則

拋出java.lang.UnsupportedOperationException。你必須通過Student1.addCourse()

向特定的Student1對象添加一個新課程。就好像,你必須讓顧客自己向購物車裏放食物,

而不能在顧客毫不知情下,偷偷向其購物車裏放食物。

 

 

三、多線程

35. 並行和併發有什麼區別?

併發,是在同一個cpu上同時(不是真正的同時,而是看來是同時,因爲cpu要在多個程序間切換)運行多個程序。

並行,是每個cpu運行一個程序。簡而言之就是併發是多個事件在同一時間段執行,而並行是多個事件在同一時間點執行。(請仔細品味以上兩個圖)打個比方。併發,就像一個人(cpu)喂2個孩子(程序),輪換着每人喂一口,表面上兩個孩子都在吃飯。並行,就是2個人喂2個孩子,兩個孩子也同時在吃飯。

 

 

 

36. 線程和進程的區別?什麼是線程安全

進程:是併發執行的程序在執行過程中分配和管理資源的基本單位,是一個動態概念,競爭計算機系統資源的基本單位。

線程:是進程的一個執行單元,是進程內科調度實體。比進程更小的獨立運行的基本單位。線程也被稱爲輕量級進程。

一個程序至少一個進程,一個進程至少一個線程。

進程線程的區別:

    地址空間:同一進程的線程共享本進程的地址空間,而進程之間則是獨立的地址空間。

    資源擁有:同一進程內的線程共享本進程的資源如內存、I/Ocpu等,但是進程之間的資源是獨立的。

     一個進程崩潰後,在保護模式下不會對其他進程產生影響,但是一個線程崩潰整個進程都死掉。所以多進程要比多線程健壯。

進程切換時,消耗的資源大,效率高。所以涉及到頻繁的切換時,使用線程要好於進程。同樣如果要求同時進行並且又要共享某些變量的併發操作,只能用線程不能用進程

    執行過程:每個獨立的進程程有一個程序運行的入口、順序執行序列和程序入口。但是線程不能獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。

    線程是處理器調度的基本單位,但是進程不是。

兩者均可併發執行。

線程安全是多線程編程時的計算機程序代碼中的一個概念。

在擁有共享數據的多條線程並行執行的程序中,線程安全的代碼會通過同步機制保證各個線程都可以正常且正確的執行,不會出現數據污染等意外情況。

線程安全問題大多是由全局變量靜態變量引起的,局部變量逃逸也可能導致線程安全問題。若每個線程中對全局變量、靜態變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時執行寫操作,一般都需要考慮線程同步,否則的話就可能影響線程安全。

37. 守護線程是什麼?

守護線程(即daemon thread),是個服務線程,準確地來說就是服務其他的線程,這是它的作用——而其他的線程只有一種,那就是用戶線程。所以java裏線程分2種,

1、守護線程,比如垃圾回收線程,就是最典型的守護線程。

2、用戶線程,就是應用程序裏的自定義線程。

 

 

38. 創建線程有哪幾種方式?

 

1. 繼承 Thread 類,然後調用 start 方法。

class SampleThread extends Thread {

    //重寫run方法,線程運行後,跑的就是run方法

    public void run(){

       //System.out.println("");

    }

 

    public static void main(String[] args){

       Thread t1 = new SampleThread();

       Thread t2 = new SampleThread();

       t1.start();  //線程運行,調用的 run()方法.

       t2.start(); //線程運行,調用的 run()方法.. 

    }

}

2. 實現 Runnable 接口的 run 方法, 然後再用 Thread 類包裹後,調用 start 方法。

 

class A implements Runnable{

    @Override

    public void run() {

        // implement run method here

    }

 

    public static void main() {

        final A obj = new A();

 

        Thread t1 = new Thread(new A());

 

        t1.start();

    }

 

}

 

39. 說一下 runnable callable 有什麼區別?

相同點:兩者都是接口,都需要調用Thread.start()

不同:實現callable接口的任務線程能返回執行結果,而實現Runnable接口的任務線程不能返回結果

callable接口的call()方法允許拋出異常,而runnable()接口的run()方法的異常只能在內部消化,不能繼續上拋;

40. 線程有哪些狀態?

新建new新創建了一個線程對象。

可運行runnable線程對象創建後,其他線程(比如main線程)調用了該對象的start()方法。該狀態的線程位於可運行線程池中,等待被線程調度選中,獲取cpu 的使用權 。

運行running可運行狀態(runnable)的線程獲得了cpu 時間片(timeslice) ,執行程序代碼。

阻塞blocked阻塞狀態是指線程因爲某種原因放棄了cpu 使用權,也即讓出了cpu timeslice,暫時停止運行。直到線程進入可運行(runnable)狀態,纔有機會再次獲得cpu timeslice 轉到運行(running)狀態。阻塞的情況分三種: 

死亡dead

41. sleep() wait() 有什麼區別?

sleep():當前線程會放棄cpu,但是不會放棄同步鎖

wait(): 當前線程放棄cpu同時會放棄互斥鎖

sleep():方法是線程類(Thread)的靜態方法,讓調用線程進入睡眠狀態,讓出執行機會給其他線程,等到休眠時間結束後,線程進入就緒狀態和其他線程一起競爭cpu的執行時間。因爲sleep() static靜態的方法,他不能改變對象的機鎖,當一個synchronized塊中調用了sleep() 方法,線程雖然進入休眠,但是對象的機鎖沒有被釋放,其他線程依然無法訪問這個對象。

wait()wait()Object類的方法,當一個線程執行到wait方法時,它就進入到一個和該對象相關的等待池,同時釋放對象的機鎖,使得其他線程能夠訪問,可以通過notifynotifyAll方法來喚醒等待的線程

 

42. notify() notifyAll()有什麼區別?

如果線程調用了對象的 wait()方法,那麼線程便會處於該對象的等待池中,等待池中的線程不會去競爭該對象的鎖。

 

當有線程調用了對象的 notifyAll()方法(喚醒所有 wait 線程)或 notify()方法(只隨機喚醒一個 wait 線程),被喚醒的的線程便會進入該對象的鎖池中,鎖池中的線程會去競爭該對象鎖。也就是說,調用了notify後只有一個線程會由等待池進入鎖池,而notifyAll會將該對象等待池內的所有線程移動到鎖池中,等待鎖競爭。

 

優先級高的線程競爭到對象鎖的概率大,假若某線程沒有競爭到該對象鎖,它還會留在鎖池中,唯有線程再次調用 wait()方法,它纔會重新回到等待池中。而競爭到對象鎖的線程則繼續往下執行,直到執行完了 synchronized 代碼塊,它會釋放掉該對象鎖,這時鎖池中的線程會繼續競爭該對象鎖

43. 線程的 run() start()有什麼區別?

run():只是調用方法

start():開啓一個線程每個線程都是通過某個特定Thread對象所對應的方法run()來完成其操作的,方法run()稱爲線程體。通過調用Thread類的start()方法來啓動一個線程。

start()方法來啓動一個線程,真正實現了多線程運行。這時無需等待run方法體代碼執行完畢,可以直接繼續執行下面的代碼; 這時此線程是處於就緒狀態, 並沒有運行。 然後通過此Thread類調用方法run()來完成其運行狀態, 這裏方法run()稱爲線程體,它包含了要執行的這個線程的內容, Run方法運行結束, 此線程終止。然後CPU再調度其它線程。

 

run()方法是在本線程裏的,只是線程裏的一個函數,而不是多線程的。 如果直接調用run(),其實就相當於是調用了一個普通函數而已,直接待用run()方法必須等待run()方法執行完畢才能執行下面的代碼,所以執行路徑還是隻有一條,根本就沒有線程的特徵,所以在多線程執行時要使用start()方法而不是run()方法。

44. 創建線程池有哪幾種方式?

. newFixedThreadPool(int nThreads)

創建一個固定長度的線程池,每當提交一個任務就創建一個線程,直到達到線程池的最大數量,這時線程規模將不再變化,當線程發生未預期的錯誤而結束時,線程池會補充一個新的線程。

. newCachedThreadPool()

創建一個可緩存的線程池,如果線程池的規模超過了處理需求,將自動回收空閒線程,而當需求增加時,則可以自動添加新線程,線程池的規模不存在任何限制。

. newSingleThreadExecutor()

這是一個單線程的Executor,它創建單個工作線程來執行任務,如果這個線程異常結束,會創建一個新的來替代它;它的特點是能確保依照任務在隊列中的順序來串行執行。

. newScheduledThreadPool(int corePoolSize)

創建了一個固定長度的線程池,而且以延遲或定時的方式來執行任務,類似於Timer

 

45. 線程池都有哪些狀態?

線程池有5種狀態:Running、ShutDown、Stop、Tidying、Terminated。

1. RUNNING

(01) 狀態說明:線程池處在RUNNING狀態時,能夠接收新任務,以及對已添加的任務進行處理。

(02) 狀態切換:線程池的初始化狀態是RUNNING。換句話說,線程池被一旦被創建,就處於RUNNING狀態!

道理很簡單,在ctl的初始化代碼中(如下),就將它初始化爲RUNNING狀態,並且"任務數量"初始化爲0

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

2. SHUTDOWN

 (01) 狀態說明:線程池處在SHUTDOWN狀態時,不接收新任務,但能處理已添加的任務。

(02) 狀態切換:調用線程池的shutdown()接口時,線程池由RUNNING -> SHUTDOWN

3. STOP

(01) 狀態說明:線程池處在STOP狀態時,不接收新任務,不處理已添加的任務,並且會中斷正在處理的任務。

(02) 狀態切換:調用線程池的shutdownNow()接口時,線程池由(RUNNING or SHUTDOWN ) -> STOP

4. TIDYING

(01) 狀態說明:當所有的任務已終止,ctl記錄的"任務數量"0,線程池會變爲TIDYING狀態。當線程池變爲TIDYING狀態時,會執行鉤子函數terminated()terminated()ThreadPoolExecutor類中是空的,若用戶想在線程池變爲TIDYING時,進行相應的處理;可以通過重載terminated()函數來實現。

(02) 狀態切換:當線程池在SHUTDOWN狀態下,阻塞隊列爲空並且線程池中執行的任務也爲空時,就會由 SHUTDOWN -> TIDYING

當線程池在STOP狀態下,線程池中執行的任務爲空時,就會由STOP -> TIDYING

5. TERMINATED

(01) 狀態說明:線程池徹底終止,就變成TERMINATED狀態。

(02) 狀態切換:線程池處在TIDYING狀態時,執行完terminated()之後,就會由 TIDYING -> TERMINATED

 

46. 線程池中 submit() execute()方法有什麼區別?

    接收的參數不一樣

    submit有返回值,而execute沒有

    submit方便Exception處理

47. Java 程序中怎麼保證多線程的運行安全?

1、使用synchronied關鍵字,可以用於代碼塊,方法(靜態方法,同步鎖是當前字節碼對象;實例方法,同步鎖是實例對象)

2、使用volatile 關鍵字,防止指令重排,被volatile修飾的變量的值,將不會被本地線程緩存,所有對該變量的讀寫都是直接操作共享內存,從而確保多個線程能正確的處理該變量

3lock鎖機制

4、使用線程安全的類,比如VectorHashTableStringBuffer

線程安全在三個方面體現:

    原子性:提供互斥訪問,同一時刻只能有一個線程對數據進行操作,(atomic,synchronized);

    可見性:一個線程對主內存的修改可以及時地被其他線程看到,(synchronized,volatile);

    有序性:一個線程觀察其他線程中的指令執行順序,由於指令重排序,該觀察結果一般雜亂無序,(happens-before原則)

49. 什麼是死鎖?

死鎖是指兩個或兩個以上的進程在執行過程中,由於競爭資源或者由於彼此通信而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱爲死鎖進程。是操作系統層面的一個錯誤,是進程死鎖的簡稱,最早在 1965 年由 Dijkstra 在研究銀行家算法時提出的,它是計算機操作系統乃至整個併發程序設計領域最難處理的問題之一。

50. 怎麼防止死鎖?

死鎖的四個必要條件

互斥條件:進程對所分配到的資源不允許其他進程進行訪問,若其他進程訪問該資源,只能等待,直至佔有該資源的進程使用完成後釋放該資源

 

請求和保持條件:進程獲得一定的資源之後,又對其他資源發出請求,但是該資源可能被其他進程佔有,此事請求阻塞,但又對自己獲得的資源保持不放

 

不可剝奪條件:是指進程已獲得的資源,在未完成使用之前,不可被剝奪,只能在使用完後自己釋放

 

環路等待條件:是指進程發生死鎖後,若干進程之間形成一種頭尾相接的循環等待資源關係

 

 

51. ThreadLocal 是什麼?有哪些使用場景?

線程局部變量是侷限於線程內部的變量,屬於線程自身所有,不在多個線程間共享,java提供ThreadLocal類來支持線程局部變量,是一種實現線程安全的方式,但是在管理環境下(如web服務器)使用線程局部變量的時候要特別小心,在這種請款下,工作線程的生命週期比 任何應用變量的生命週期都要長,任何線程局部變量一旦在工作完成後沒有釋放,java應用就存在內存泄漏的風險。

52. 說一下 Synchronized 底層實現原理?          

java中虛擬機中的同步synchronization synchronization 基於進入和退出管程(monitor)對象實現,無論是顯示同步(有明確的monitroenter和monitorexit指令,即同步代碼塊)還是隱式同步都是如此

synchronization可以保證方法或者代碼塊在運行時,同一時刻只有一個方法可以進入到臨界區,同時它還可以保證共享變量的內存可見性。

java中每一個對象都可以作爲鎖,這是synchronization實現同步的基礎:

普通同步方法,鎖是當前實例對象

靜態同步方法,鎖是當前類的class對象

同步方法塊,鎖是括號裏面的對象

 

53. Synchronized volatile 的區別是什麼?

volatile本質是在告訴jvm當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取,synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。

volatile僅能使用在變量級別,synchronzed則可以使用在變量、方法、和類級別的

volatile僅能實現變量的修改可見性,不能保證原子性,而synchronized則可以保證變量的修改可見性和原子性

volatile不會造成線程的阻塞,synchronized可能會造成

volatile標記的變量不會被編譯器優化,synchronized標記的變量可以被編譯器優化

 

54. Synchronized Lock 有什麼區別?

首先synchronized是java內置關鍵字,在jvm層面,Lock是個java類;

synchronized無法判斷是否獲取鎖的狀態,Lock可以判斷是否獲取到鎖;

synchronized會自動釋放鎖(a 線程執行完同步代碼會釋放鎖 ;b 線程執行過程中發生異常會釋放鎖),Lock需在finally中手工釋放鎖(unlock()方法釋放鎖),否則容易造成線程死鎖;

用synchronized關鍵字的兩個線程1和線程2,如果當前線程1獲得鎖,線程2線程等待。如果線程1阻塞,線程2則會一直等待下去,而Lock鎖就不一定會等待下去,如果嘗試獲取不到鎖,線程可以不用一直等待就結束了;

synchronized的鎖可重入、不可中斷、非公平,而Lock鎖可重入、可判斷、可公平(兩者皆可);

Lock鎖適合大量同步的代碼的同步問題,synchronized鎖適合代碼少量的同步問題

 

55. Synchronized ReentrantLock 區別是什麼?

synchronized是和if、else、for、while一樣的關鍵字,ReentrantLock是類,這是二者的本質區別。既然ReentrantLock是類,那麼它就提供了比synchronized更多更靈活的特性,可以被繼承、可以有方法、可以有各種各樣的類變量,ReentrantLock比synchronized的擴展性體現在幾點上:

 ReentrantLock可以對獲取鎖的等待時間進行設置,這樣就避免了死鎖

 ReentrantLock可以獲取各種鎖的信息

 ReentrantLock可以靈活地實現多路通知 

 

另外,二者的鎖機制其實也是不一樣的:ReentrantLock底層調用的是Unsafe的park方法加鎖,synchronized操作的應該是對象頭中mark word

56. 說一下 Atomic 的原理?

Atomic包中的類基本的特性就是在多線程環境下,當有多個線程同時對單個(包括基本類型及引用類型)變量進行操作時,具有排他性,即當多個線程同時對該變量的值進行更新時,僅有一個線程能成功,而未成功的線程可以向自旋鎖一樣,繼續嘗試,一直等到執行成功。

 

Atomic系列的類中的核心方法都會調用unsafe類中的幾個本地方法。我們需要先知道一個東西就是Unsafe類,全名爲:sun.misc.Unsafe,這個類包含了大量的對C代碼的操作,包括很多直接內存分配以及原子操作的調用,而它之所以標記爲非安全的,是告訴你這個裏面大量的方法調用都會存在安全隱患,需要小心使用,否則會導致嚴重的後果,例如在通過unsafe分配內存的時候,如果自己指定某些區域可能會導致一些類似C++一樣的指針越界到其他進程的問題。

 

四、反射

 

57. 什麼是反射?

         在java運行環境中,對於任意一個類,能否知道這個類有哪些屬性和方法,對於任意一個對象,能否調用任意的方法

java反射機制主要提供以下功能:

         在運行時判斷任意一個對象所屬的類

         在運行時構造任意一個類的對象

         在運行時判斷任意一個類所具有的成員變量和方法

         在運行時調用任意一個對象的方法

58. 什麼是 Java 序列化?什麼情況下需要序列化?

java序列化,就是把java對象變爲二進制對象,便於存儲和在網絡上傳輸

什麼情況下需要:

當你想把你內存中的對象狀態保存到一個文件中或者數據庫中的時候

當你想用套接字在網絡上傳送對象的時候

當你想通過RMI傳輸對象的時候

59. 動態代理是什麼?有哪些應用?

動態代理:在運行時,創建目標類,可以調用和擴展目標類的方法。

Java 中實現動態的方式:JDK 中的動態代理 和 Java類庫 CGLib

           當想要給實現了某個接口的類中的方法,加一些額外的處理,比如加日誌,加事務,加權限,Spring的AOP等。

應用場景如:

  • 統計每個 api 的請求耗時
  • 統一的日誌輸出
  • 校驗被調用的 api 是否已經登錄和權限鑑定
  • Spring的 AOP 功能模塊就是採用動態代理的機制來實現切面編程

 

60. 怎麼實現動態代理?

 

https://blog.csdn.net/meism5/article/details/90413999

五、對象拷貝

61. 爲什麼要使用克隆?

 

62. 如何實現對象克隆?

63. 深拷貝和淺拷貝區別是什麼?

六、JAVAWEB

64. JSP servlet 有什麼區別?

65. JSP 有哪些內置對象?作用分別是什麼?

66. 說一下 JSP 4 種作用域?

page:當前頁面

session:瀏覽器打開到關閉

application:整個應用

request:http請求到服務器到處理結束返回響應的整個過程。

 

67. Session Cookie 有什麼區別?

 

68. 說一下 Session的工作原理?

69. 如果客戶端禁止 Cookie 能實現 Session 還能用嗎?

70. Spring MVC Struts 的區別是什麼?

71. 如何避免 SQL 注入?

72. 什麼是 XSS 攻擊,如何避免?

73. 什麼是 CSRF 攻擊,如何避免?

七、異常

74. throw throws 的區別?

75. finalfinallyfinalize 有什麼區別?

76. try-catch-finally 中哪個部分可以省略?

77. try-catch-finally 中,如果 catch return 了,finally 還會執行嗎?

78. 常見的異常類有哪些?

八、網絡

79. HTTP 響應碼 301 302 代表的是什麼?有什麼區別?

80. forward redirect 的區別?

81. 簡述 TCP UDP 的區別?

82. TCP爲什麼要三次握手,兩次不行嗎?爲什麼?

83. 說一下 TCP粘包是怎麼產生的?

84. OSI 的七層模型都有哪些?

85. ****Get Post 請求有哪些區別?

86. 如何實現跨域?

87. 說一下 JSONP 實現原理?

九、設計模式

88. 說一下你熟悉的設計模式?

89. 簡單工廠和抽象工廠有什麼區別?

十、Spring/Spring MVC

90. 爲什麼要使用 Spring

91. 解釋一下什麼是 AOP

92. 解釋一下什麼是 IOC

93. Spring 有哪些主要模塊?

94. Spring 常用的注入方式有哪些?

95. Spring 中的 Bean 是線程安全的嗎?

96. Spring 支持幾種 Bean 的作用域?

97. Spring 自動裝配 Bean 有哪些方式?

98. Spring 事務實現方式有哪些?

99. 說一下 Spring 的事務隔離?

100. 說一下 Spring MVC 運行流程?

101. Spring MVC 有哪些組件?

102. @RequestMapping 的作用是什麼?

103. @Autowired 的作用是什麼?

十一、Spring Boot/Spring Cloud

104. 什麼是 Spring Boot

105. 爲什麼要用 Spring Boot

106. Spring Boot 核心配置文件是什麼?yml

 

107. Spring Boot 配置文件有哪幾種類型?它們有什麼區別?

108. Spring Boot 有哪些方式可以實現熱部署?

109. JPA Hibernate 有什麼區別?

110. 什麼是 Spring Cloud

111. Spring Cloud 斷路器的作用是什麼?

112. Spring Cloud 的核心組件有哪些?

十二、Hibernate

113. 爲什麼要使用 Hibernate

114. 什麼是 ORM 框架?

115. Hibernate 中如何在控制檯查看打印的 SQL 語句?

116. Hibernate 有幾種查詢方式?

117. Hibernate 實體類可以被定義爲 final 嗎?

118. Hibernate 中使用 Integer int 做映射有什麼區別?

119. Hibernate 是如何工作的?

120. get() load()的區別?

121. 說一下 Hibernate 的緩存機制?

122. Hibernate 對象有哪些狀態?

123. Hibernate getCurrentSession openSession 的區別是什麼?

124. Hibernate 實體類必須要有無參構造函數嗎?爲什麼?

十三、Mybatis

125. Mybatis #{} ${}的區別是什麼?

126. Mybatis 有幾種分頁方式?

127. RowBounds 是一次性查詢全部結果嗎?爲什麼?

128. Mybatis 邏輯分頁和物理分頁的區別是什麼?

129. Mybatis 是否支持延遲加載?延遲加載的原理是什麼?

130. 說一下 Mybatis 的一級緩存和二級緩存?

131. Mybatis Hibernate 的區別有哪些?

132. Mybatis 有哪些執行器(Executor)?

133. Mybatis 分頁插件的實現原理是什麼?

134. Mybatis 如何編寫一個自定義插件?

十四、RabbitMQ

135. RabbitMQ 的使用場景有哪些?

136. RabbitMQ有哪些重要的角色?

137. RabbitMQ有哪些重要的組件?

138. RabbitMQ VHost 的作用是什麼?

139. RabbitMQ的消息是怎麼發送的?

140. RabbitMQ怎麼保證消息的穩定性?

141. RabbitMQ怎麼避免消息丟失?

142. 要保證消息持久化成功的條件有哪些?

143. RabbitMQ持久化有什麼缺點?

144. RabbitMQ有幾種廣播類型?

145. RabbitMQ怎麼實現延遲消息隊列?

146. RabbitMQ集羣有什麼用?

147. RabbitMQ節點的類型有哪些?

148. RabbitMQ集羣搭建需要注意哪些問題?

149. RabbitMQ每個節點是其他節點的完整拷貝嗎?爲什麼?

150. RabbitMQ集羣中唯一一個磁盤節點崩潰了會發生什麼情況?

151. RabbitMQ對集羣節點停止順序有要求嗎?

十五、Kafka

152. Kafka 可以脫離 ZooKeeper 單獨使用嗎?爲什麼?

153. Kafka有幾種數據保留的策略?

154. Kafka同時設置了 7 天和 10G 清除數據,到第五天的時候消息達到了 10G,這個時候 Kafka將如何處理?

155. 什麼情況會導致 Kafka運行變慢?

156. 使用 Kafka集羣需要注意什麼?

十六、ZooKeeper

157. ZooKeeper 是什麼?

158. ZooKeeper都有哪些功能?

159. ZooKeeper有幾種部署模式?

160. ZooKeeper怎麼保證主從節點的狀態同步?

161. 集羣中爲什麼要有主節點?

162. 集羣中有 3 臺服務器,其中一個節點宕機,這個時候 ZooKeeper還可以使用嗎?

163. 說一下 ZooKeeper 的通知機制?

十七、MySQL

164. 數據庫的三範式是什麼?

165. 一張自增表裏面總共有 7 條數據,刪除了最後 2 條數據,重啓 MySQL 數據庫,又插入了一條數據,此時 ID 是幾?

166. 如何獲取當前數據庫版本?

167. 說一下 ACID 是什麼?

168. Char VarChar 的區別是什麼?

169. Float Double 的區別是什麼?

170. MySQL 的內連接、左連接、右連接有什麼區別?

171. MySQL索引是怎麼實現的?

172. 怎麼驗證 MySQL的索引是否滿足需求?

173. 說一下數據庫的事務隔離?

174. 說一下 MySQL常用的引擎?

175. 說一下 MySQL的行鎖和表鎖?

176. 說一下樂觀鎖和悲觀鎖?

177. MySQL問題排查都有哪些手段?

178. 如何做 MySQL的性能優化?

十八、Redis

179. Redis 是什麼?都有哪些使用場景?

180. Redis有哪些功能?

181. Redis MemeCache 有什麼區別?

182. Redis爲什麼是單線程的?

183. 什麼是緩存穿透?怎麼解決?

184. Redis支持的數據類型有哪些?

185. Redis支持的 Java 客戶端都有哪些?

186. Jedis Redisson 有哪些區別?

187. 怎麼保證緩存和數據庫數據的一致性?

188. Redis持久化有幾種方式?

189. Redis怎麼實現分佈式鎖?

190. Redis分佈式鎖有什麼缺陷?

191. Redis如何做內存優化?

192. Redis淘汰策略有哪些?

193. Redis常見的性能問題有哪些?該如何解決?

十九、JVM

194. 說一下 JVM 的主要組成部分?及其作用?

195. 說一下 JVM運行時數據區?

196. 說一下堆棧的區別?

197. 隊列和棧是什麼?有什麼區別?

198. 什麼是雙親委派模型?

199. 說一下類加載的執行過程?

200. 怎麼判斷對象是否可以被回收?

201. Java 中都有哪些引用類型?

202. 說一下 JVM有哪些垃圾回收算法?

203. 說一下 JVM有哪些垃圾回收器?

204. 詳細介紹一下 CMS 垃圾回收器?

205. 新生代垃圾回收器和老生代垃圾回收器都有哪些?有什麼區別?

206. 簡述分代垃圾回收器是怎麼工作的?

207. 說一下 JVM調優的工具?

208. 常用的 JVM調優的參數都有哪些?

 

發佈了27 篇原創文章 · 獲贊 32 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章