這麼經典全面的java崗面試題不瞭解下?

Java面試的一些題目,個人覺得很經典轉過來了,答案准備自己找,保證質量所以貼個原創不斷更新,當然也可以去原文找。


題目區

Java基礎:

面向對象和麪向過程的區別

Java的四個基本特性(抽象、封裝、繼承,多態)

Overload和Override的區別

構造器Constructor是否可被override

訪問控制符public,protected,private,以及默認的區別

是否可以繼承String類

String和StringBuffer、StringBuilder的區別

hashCode和equals方法的關係

抽象類和接口的區別

自動裝箱與拆箱

什麼是泛型、爲什麼要使用以及泛型擦除

Java中的集合類及關係圖

HashMap實現原理(看源代碼)

HashTable實現原理(看源代碼)

HashMap和HashTable區別

HashTable如何實現線程安全(看源代碼)

ArrayList和vector區別(看源代碼)

ArrayList和LinkedList區別及使用場景

Collection和Collections的區別

Concurrenthashmap實現原理(看源代碼)

Error、Exception區別

Unchecked Exception和Checked Exception,各列舉幾個

Java中如何實現代理機制(JDK、CGLIB)

多線程的實現方式

線程的狀態轉換

如何停止一個線程

什麼是線程安全

如何保證線程安全

Synchronized如何使用

synchronized和Lock的區別

多線程如何進行信息交互

sleep和wait的區別(考察的方向是是否會釋放鎖)

多線程與死鎖

如何才能產生死鎖

什麼叫守護線程,用什麼方法實現守護線程

Java線程池技術及原理

java併發包concurrent及常用的類

volatile關鍵字

Java中的NIO,BIO,AIO分別是什麼

IO和NIO區別

序列化與反序列化

常見的序列化協議有哪些

內存溢出和內存泄漏的區別

Java內存模型及各個區域的OOM,如何重現OOM

出現OOM如何解決

用什麼工具可以查出內存泄漏

Java內存管理及回收算法

Java類加載器及如何加載類(雙親委派)

xml解析方式

Statement和PreparedStatement之間的區別

JavaEE:

servlet生命週期及各個方法

servlet中如何自定義filter

JSP原理

JSP和Servlet的區別

JSP的動態include和靜態include

Struts中請求處理過程

MVC概念

Spring mvc與Struts區別

Hibernate/Ibatis兩者的區別

Hibernate一級和二級緩存

Hibernate實現集羣部署

Hibernate如何實現聲明式事務

簡述Hibernate常見優化策略

Spring bean的加載過程(推薦看Spring的源碼)

Spring如何實現AOP和IOC

Spring bean注入方式

Spring的事務管理(推薦看Spring的源碼)

Spring事務的傳播特性

springmvc原理

springmvc用過哪些註解

Restful有幾種請求

Restful好處

Tomcat,Apache,JBoss的區別

memcached和redis的區別

有沒有遇到中文亂碼問題,如何解決的

如何理解分佈式鎖

你知道的開源協議有哪些

json和xml區別

設計模式:

設計模式的六大原則

常用的設計模式

用一個設計模式寫一段代碼或畫出一個設計模式的UML

如何理解MVC

高內聚,低耦合方面的理解

算法:

深度優先、廣度優先算法

排序算法及對應的時間複雜度和空間複雜度

寫一個排序算法

查找算法

B+樹和二叉樹查找時間複雜度

KMP算法、hash算法

常用的hash算法有哪些

如何判斷一個單鏈表是否有環?

給你一萬個數,如何找出裏面所有重複的數?用所有你能想到的方法,時間複雜度和空間複雜度分別是多少?

給你一個數組,如何裏面找到和爲K的兩個數?

100000個數找出最小或最大的10個?

一堆數字裏面繼續去重,要怎麼處理?

數據結構:

隊列、棧、鏈表、樹、堆、圖

編碼實現隊列、棧

Linux:

linux常用命令

如何查看內存使用情況

Linux下如何進行進程調度

操作系統:

操作系統什麼情況下會死鎖

產生死鎖的必要條件

死鎖預防

數據庫:

範式

數據庫事務隔離級別

數據庫連接池的原理

樂觀鎖和悲觀鎖

如何實現不同數據庫的數據查詢分頁

SQL注入的原理,如何預防

數據庫索引的實現(B+樹介紹、和B樹、R樹區別)

SQL性能優化

數據庫索引的優缺點以及什麼時候數據庫索引失效

Redis的存儲結構

網絡:

OSI七層模型以及TCP/IP四層模型

HTTP和HTTPS區別

HTTP報文內容

get提交和post提交的區別

get提交是否有字節限制,如果有是在哪限制的

TCP的三次握手和四次揮手

session和cookie的區別

HTTP請求中Session實現原理

redirect與forward區別

DNS

TCP和UDP區別

安全:

如果客戶端不斷的發送請求連接會怎樣

DDos攻擊

DDos預防


答案區
面向對象和麪向過程的區別
資料

面向過程就是分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就可以了。面向對象是把構成問題事務分解成各個對象,建立對象的目的不是爲了完成一個步驟,而是爲了描敘某個事物在整個解決問題的步驟中的行爲。
例如五子棋,面向過程的設計思路就是首先分析問題的步驟:1、開始遊戲,2、黑子先走,3、繪製畫面,4、判斷輸贏,5、輪到白子,6、繪製畫面,7、判斷輸贏,8、返回步驟2,9、輸出最後結果。把上面每個步驟用分別的函數來實現,問題就解決了。
而面向對象的設計則是從另外的思路來解決問題。整個五子棋可以分爲
1、黑白雙方,這兩方的行爲是一模一樣的,2、棋盤系統,負責繪製畫面,3、規則系統,負責判定諸如犯規、輸贏等。第一類對象(玩家對象)負責接受用戶輸入,並告知第二類對象(棋盤對象)棋子佈局的變化,棋盤對象接收到了棋子的i變化就要負責在屏幕上面顯示出這種變化,同時利用第三類對象(規則系統)來對棋局進行判定。
可以明顯地看出,面向對象是以功能來劃分問題,而不是步驟。同樣是繪製棋局,這樣的行爲在面向過程的設計中分散在了總多步驟中,很可能出現不同的繪製版本,因爲通常設計人員會考慮到實際情況進行各種各樣的簡化。而面向對象的設計中,繪圖只可能在棋盤對象中出現,從而保證了繪圖的統一。
功能上的統一保證了面向對象設計的可擴展性。比如我要加入悔棋的功能,如果要改動面向過程的設計,那麼從輸入到判斷到顯示這一連串的步驟都要改動,甚至步驟之間的循序都要進行大規模調整。如果是面向對象的話,只用改動棋盤對象就行了,棋盤系統保存了黑白雙方的棋譜,簡單回溯就可以了,而顯示和規則判斷則不用顧及,同時整個對對象功能的調用順序都沒有變化,改動只是局部的。
再比如我要把這個五子棋遊戲改爲圍棋遊戲,如果你是面向過程設計,那麼五子棋的規則就分佈在了你的程序的每一個角落,要改動還不如重寫。但是如果你當初就是面向對象的設計,那麼你只用改動規則對象就可以了,五子棋和圍棋的區別不就是規則嗎?(當然棋盤大小好像也不一樣,但是你會覺得這是一個難題嗎?直接在棋盤對象中進行一番小改動就可以了。)而下棋的大致步驟從面向對象的角度來看沒有任何變化。
當然,要達到改動只是局部的需要設計的人有足夠的經驗,使用對象不能保證你的程序就是面向對象,初學者或者很蹩腳的程序員很可能以面向對象之虛而行面向過程之實,這樣設計出來的所謂面向對象的程序很難有良好的可移植性和可擴展性。

Java的四個基本特性(抽象、封裝、繼承,多態)
資料

一.封裝

封裝:把對象的屬性和方法結合成一個獨立的整體,隱藏實現細節,並提供對外訪問的接口。

封裝的優點:

1.隱藏實現細節。

2.安全性。

比如你在程序中私有化了age屬性,並提供了對外的get和set方法,當外界 使用set方 方法爲屬性設值的時候 ,你可以在set方法裏面做個if判斷,把值設值在0-80歲,那樣他就不能隨意賦值了。
3.增加代碼複用性。比如在工具中封裝的各種方法,可以任意調用,而不用每處去實現細節。
4。模塊化。
封裝分爲封裝屬性,方法,類等等。有利於代碼調試,相互配合。
二.繼承
繼承的概念:從已知的一個類中派生出一個新的類,叫子類。子類實現了父類所有非私有化的屬性和方法,並根據實際需求擴展出新的行爲。

繼承的好處:

1.繼承是傳遞的,易於在其基礎上構造和擴充。

2.簡化對事物的描繪,使得層次更加清晰。

3.減少代碼冗餘。

4.提高可維護性。

三.多態

多態的概念:多個不同的對象對同一消息作出響應。同一消息根據不同的對象而採用各種不同的方法。

多態的好處:主要是利於擴展。
四。抽象與接口
抽象的概念:通過特定的實例抽取出共同的特徵行成概念的過程。
抽象方法:

被abstract修飾的方法是抽象方法。抽象方法沒有方法體。修飾符返回類型爲 函數名();抽象方法的修飾只能用public或protected或者沒有修飾。不能被final,static,private修飾。

抽象與接口的區別:

不同:

1.接口可以多實現,而抽象類只能單繼承。

2.抽象類可以具有非抽向的方法和構造方法,變量。但是接口只有抽象方法,靜態常量。

3.抽象類和子類有父子關係,子類能擁有弗雷德一些屬性。接口雖然某個類實現一個接口,但由於接口中的變量都爲靜態常量,不存在繼承關係。

相同點:

1.無論接口還是抽象類,都無法被直接實例化,其自身實例化需要靠實現類或者子類實現。

Overload和Override的區別
資料

Override是重寫:
方法名稱、參數個數,類型,順序,返回值類型都是必須和父類方法一致的。它的關係是父子關係,
重寫是子類對父類的允許訪問的方法的實現過程進行重新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫!
Overload是重載:方法名稱不變,其餘的都是可以變更的。它的關係是同一個類,同一個方法名,不同的方法參數或返回值。
重載(overloading) 是在一個類裏面,方法名字相同,而參數不同。返回類型可以相同也可以不同。
備註:它們都是是Java多態性的不同表現

構造器Constructor是否可被override

構造器是用來生成一個類的實例是用來初始化這個實例用的,構造器Constructor不能被繼承,因此不能重寫Override,但可以被重載Overload。Constructor不能被繼承,所以Constructor也就不能被override。每一個類必須有自己的構造函數,負責構造自己這部分的構造。子類不會覆蓋父類的構造函數,相反必須負責在一開始調用父類的構造函數。
總之:構造器不是方法,那麼用來修飾方法特性的所有修飾符都不能用來修飾構造器(並不等與構造器具備這些特性,雖然不能用static修飾構造器,但它卻有靜態特性)構造器只能用 public private protected這三個權限修飾符,且不能有返回語句。

訪問控制符public,protected,private,以及默認的區別
資料
這裏寫圖片描述

類的成員不寫訪問修飾符默認爲default,默認對於同一個包的其他類相當於公開(public),對於不是同一個包的其他類相當於私有(private)。受保護(protected)對子類相當於公開,對於不是同一個包沒有父子關係的類相當於私有。Java中,外部類的修飾符只能是public或默認,類的成員(包括內部類)的修飾符可以是以上四種。

是否可以繼承String類
不可以,因爲String類有final修飾符,而final修飾的類是不能被繼承的,實現細節不允許改變。
String和StringBuffer、StringBuilder的區別
資料

首先 `StringBuffer和StringBuilder都繼承自AbstractStringBuilder這個類,而AbstractStringBuilder和String都繼承自超類Object。
1、執行速度:
StringBuilder > StringBuffer > String
String最慢的原因:
String爲字符串常量,而StringBuilder和StringBuffer均爲字符串變量,即String對象一旦創建之後該對象是不可更改的,但後兩者的對象是變量,是可以更改的。
2. 線程安全
StringBuilder是線程不安全的,而StringBuffer是線程安全的。兩者有相同的方法,除了StringBuilders所有方法同步,以及其對象是可以修改的字符串。
3. 總結
  String:適用於少量的字符串操作的情況
  StringBuilder:適用於單線程下在字符緩衝區進行大量操作的情況
  StringBuffer:適用多線程下在字符緩衝區進行大量操作的情況

hashCode和equals方法的關係
資料

1.hashCode是爲了提高在散列結構存儲中查找的效率,在線性表中沒有作用。
2.equals和hashCode需要同時覆蓋。
3.若兩個對象equals返回true,則hashCode有必要也返回相同的int數。
4.若兩個對象equals返回false,則hashCode不一定返回不同的int數,但爲不相等的

對象生成不同hashCode值可以提高哈希表的性能。
5.若兩個對象hashCode返回相同int數,則equals不一定返回true。
6.若兩個對象hashCode返回不同int數,則equals一定返回false。
7.同一對象在執行期間若已經存儲在集合中,則不能修改影響hashCode值的相關信息,否則會導致內存泄露問題。

抽象類和接口的區別
資料

抽象類是用來捕捉子類的通用特性的 。它不能被實例化,只能被用作子類的超類。抽象類是被用來創建繼承層級裏子類的模板。 接口是抽象方法的集合。

這裏寫圖片描述

什麼時候使用抽象類和接口?
如果你擁有一些方法並且想讓它們中的一些有默認實現,那麼使用抽象類吧。
如果你想實現多重繼承,那麼你必須使用接口。由於Java不支持多繼承,子類不能夠繼承多個類,但可以實現多個接口。因此你就可以使用接口來解決它。
如果基本功能在不斷改變,那麼就需要使用抽象類。如果不斷改變基本功能並且使用接口,那麼就需要改變所有實現了該接口的類。

自動裝箱與拆箱

自動裝箱:
Java自動將原始類型值轉換成對應的對象,比如將int的變量轉換成Integer對象;
因爲這裏的裝箱和拆箱是自動進行的非人爲轉換,所以就稱作爲自動裝箱和拆箱。

什麼是泛型、爲什麼要使用以及泛型擦除
資料

泛型:本質是參數化類型。
爲什麼要使用?
創建集合的時候,往集合裏面添加數據,再次取出時,集合會忘記這數據類型,該對象的編譯類型就會變成Object類型,否則如果想要變回原來的數據類型的時候,就要強制進行轉換。創建集合的時候,我們就指定集合類型,避免這個過程。
泛型擦除?
Java的泛型處理過程都是在編譯器中進行的,編譯器首先會生成bytecode碼,這個過程是不包括泛型類型,泛型類型在編譯的時候是被擦除的,這個過程及泛型擦除。
泛型擦除的過程: 1將所有泛型參數用頂級父類類型替換 2擦除所有的參數類型

Java中的集合類及關係圖(沒理解什麼意思)
資料

List和Set繼承自Collection接口。 Set無序不允許元素重複。HashSet和TreeSet是兩個主要的實現類。
List有序且允許元素重複。ArrayList、LinkedList和Vector是三個主要的實現類。
Map也屬於集合系統,但和Collection接口沒關係。Map是key對value的映射集合,其中key列就是一個集合。key不能重複,但是value可以重複。
HashMap、TreeMap和Hashtable是三個主要的實現類。SortedSet和SortedMap接口對元素按指定規則排序,SortedMap是對key列進行排序。

HashMap實現原理
資料

HashMap基於hashing原理,我們通過put()和get()方法儲存和獲取對象。當我們將鍵值對傳遞給put()方法時,它調用鍵對象的hashCode()方法來計算hashcode,讓後找到bucket位置來儲存值對象。當獲取對象時,通過鍵對象的equals()方法找到正確的鍵值對,然後返回值對象。HashMap使用LinkedList來解決碰撞問題,當發生碰撞了,對象將會儲存在LinkedList的下一個節點中。 HashMap在每個LinkedList節點中儲存鍵值對對象。當兩個不同的鍵對象的hashcode相同時會發生什麼? 它們會儲存在同一個bucket位置的LinkedList中。鍵對象的equals()方法用來找到鍵值對。
多線程環境下,使用Hashmap進行put操作會引起死循環,導致CPU利用率接近100%,所以在併發情況下不能使用HashMap。

HashTable實現原理

不理解待填

HashMap和HashTable區別
資料(附帶HashSet和HashMap、Hashtable的區別)

1、兩者最主要的區別在於Hashtable是線程安全,而HashMap則非線程安全
Hashtable的實現方法裏面都添加了synchronized關鍵字來確保線程同步,因此相對而言HashMap性能會高一些,我們平時使用時若無特殊需求建議使用HashMap,在多線程環境下若使用HashMap需要使用Collections.synchronizedMap()方法來獲取一個線程安全的集合(Collections.synchronizedMap()實現原理是Collections定義了一個SynchronizedMap的內部類,這個類實現了Map接口,在調用方法時使用synchronized來保證線程同步,當然了實際上操作的還是我們傳入的HashMap實例,簡單的說就是Collections.synchronizedMap()方法幫我們在操作HashMap時自動添加了synchronized來實現線程同步,類似的其它Collections.synchronizedXX方法也是類似原理)
2、HashMap可以使用null作爲key,而Hashtable則不允許null作爲key
雖說HashMap支持null值作爲key,不過建議還是儘量避免這樣使用,因爲一旦不小心使用了,若因此引發一些問題,排查起來很是費事
HashMap以null作爲key時,總是存儲在table數組的第一個節點上
3、HashMap是對Map接口的實現,HashTable實現了Map接口和Dictionary抽象類
4、HashMap的初始容量爲16,Hashtable初始容量爲11,兩者的填充因子默認都是0.75
HashMap擴容時是當前容量翻倍即:capacity*2,Hashtable擴容時是容量翻倍+1即:capacity*2+1
5、兩者計算hash的方法不同,Hashtable計算hash是直接使用key的hashcode對table數組的長度直接進行取模

HashTable如何實現線程安全
資料

線程安全就是多線程訪問時(WEB網頁多用戶訪問一個頁面時),採用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其他線程不能進行訪問直到該線程讀取完,其他線程纔可使用。不會出現數據不一致或者數據污染。
其實現方式是在對應的方法上加上synchronized關鍵字,不過效率不高。

ArrayList和vector區別
資料

ArrayList和 Vector都實現了List接口, 都是通過數組實現的。
Vector是線程安全的,而ArrayList是非線程安全的。
Vector類中的方法是同步的,而ArrayList中的方法不同步。
ArrayList類僅適用於對象,不適用於原始數據類型。要使用要使用原始數據類型需要先申請一個包裝類,如ArraList <integer>
List第一次創建的時候,會有一個初始大小,隨着不斷向List中增加元素,當 List 認爲容量不夠的時候就會進行擴容。Vector缺省情況下自動增長原來一倍的數組長度,ArrayList增長原來的50%。

ArrayList和LinkedList區別及使用場景
資料

ArrayList底層是用數組實現的,可以認爲ArrayList是一個可改變大小的數組。隨着越來越多的元素被添加到ArrayList中,其規模是動態增加的。
LinkedList底層是通過雙向鏈表實現的, LinkedList和ArrayList相比,增刪的速度較快。但是查詢和修改值的速度較慢。同時,LinkedList還實現了Queue接口,所以他還提供了offer(), peek(), poll()等方法。
LinkedList更適合從中間插入或者刪除(鏈表的特性)。 ArrayList更適合檢索和在末尾插入或刪除(數組的特性)

Collection和Collections的區別
資料

java.util.Collection 是一個集合接口。它提供了對集合對象進行基本操作的通用接口方法。Collection接口在Java 類庫中有很多具體的實現。Collection接口的意義是爲各種具體的集合提供了最大化的統一操作方式。
java.util.Collections是一個包裝類。它包含有各種有關集合操作的靜態多態方法。此類不能實例化,就像一個工具類,服務於Java的Collection框架。

Concurrenthashmap實現原理
資料
Error、Exception區別
資料

首先,Error類和Exception類都是繼承Throwable類
Error(錯誤)是系統中的錯誤,程序員是不能改變的和處理的,是在程序編譯時出現的錯誤,只能通過修改程序才能修正。一般是指與虛擬機相關的問題,如系統崩潰,虛擬機錯誤,內存空間不足,方法調用棧溢等。對於這類錯誤的導致的應用程序中斷,僅靠程序本身無法恢復和和預防,遇到這樣的錯誤,建議讓程序終止。
Exception(異常)表示程序可以處理的異常,可以捕獲且可能恢復。遇到這類異常,應該儘可能處理異常,使程序恢復運行,而不應該隨意終止異常。
Exception又分爲兩類
CheckedException:(編譯時異常) 需要用try——catch顯示的捕獲,對於可恢復的異常使用CheckedException。
UnCheckedException(RuntimeException):(運行時異常)不需要捕獲,對於程序錯誤(不可恢復)的異常使用RuntimeException。Error和Exception就像是水池和水池裏的水的區別
“水池”,就是代碼正常運行的外部環境,如果水池崩潰(系統崩潰),或者池水溢出(內存溢出)等,這些都是跟水池外部環境有關。這些就是java中的error
“水池裏的水”,就是正常運行的代碼,水污染了、有雜質了,渾濁了,這些影響水質的因素就是Exception。

Unchecked Exception和Checked Exception,各列舉幾個
資料

Unchecked Exception: a. 指的是程序的瑕疵或邏輯錯誤,並且在運行時無法恢復。 b.
包括Error與RuntimeException及其子類,如:OutOfMemoryError,
UndeclaredThrowableException, IllegalArgumentException,
IllegalMonitorStateException, NullPointerException,
IllegalStateException, IndexOutOfBoundsException等。 c. 語法上不需要聲明拋出異常。

Checked Exception: a. 代表程序不能直接控制的無效外界情況(如用戶輸入,數據庫問題,網絡異常,文件丟失等) b.
除了Error和RuntimeException及其子類之外,如:ClassNotFoundException,
NamingException, ServletException, SQLException, IOException等。 c.
需要try catch處理或throws聲明拋出異常。

Java中如何實現代理機制(JDK、CGLIB)
資料

什麼是代理模式呢?代理模式是常用的Java設計模式,它的特徵是代理類與委託類有同樣的接口,代理類主要負責爲委託類預處理消息、過濾消息、把消息轉發給委託類,以及事後處理消息等。
按照代理的創建時期,一般分爲兩類:
靜態代理:由程序員或特定工具自動生成的源代碼,再對其編譯,在程序運行之前,代理的類編譯生成的.class文件就已經存在了
動態代理:在程序運行時,通過反射機制動態創建而成。
JDK動態代理:代理類和目標類實現了共同的接口,用到InvocationHandler接口。
CGLIB動態代理:代理類是目標類的子類, 用到MethodInterceptor接口

多線程的實現方式
資料

Java多線程實現方式主要有四種:繼承Thread類、實現Runnable接口、實現Callable接口通過FutureTask包裝器來創建Thread線程、使用ExecutorService、Callable、Future實現有返回結果的多線程。
其中前兩種方式線程執行完後都沒有返回值,後兩種是帶返回值的。
1、繼承Thread類創建線程
Thread類本質上是實現了Runnable接口的一個實例,代表一個線程的實例。啓動線程的唯一方法就是通過Thread類的start()實例方法。start()方法是一個native方法,它將啓動一個新線程,並執行run()方法。這種方式實現多線程很簡單,通過自己的類直接extend Thread,並複寫run()方法,就可以啓動新線程並執行自己定義的run()方法。
2、實現Runnable接口創建線程
如果自己的類已經extends另一個類,就無法直接extends Thread,此時,可以實現一個Runnable接口。

線程的狀態轉換
資料
這裏寫圖片描述

線程狀態類型
新建狀態(New):新創建了一個線程對象。
就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。
阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。阻塞的情況分三種:(一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。(三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。
死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。

如何停止一個線程
資料
在java中有以下3種方法可以終止正在運行的線程:
- 使用退出標誌,使線程正常退出,也就是當run方法完成後線程終止。
- 使用stop方法強行終止,但是不推薦這個方法,因爲stop和suspend及resume一樣都是過期作廢的方法。(不安全
- 使用interrupt方法中斷線程。

什麼是線程安全

線程安全就是多線程訪問時(WEB網頁多用戶訪問一個頁面時),採用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其他線程不能進行訪問直到該線程讀取完,其他線程纔可使用。不會出現數據不一致或者數據污染。

如何保證線程安全
資料

一般說來,確保線程安全的方法有這幾個:競爭與原子操作、同步與鎖、可重入、過度優化
1. 競爭與原子操作
多個線程同時訪問和修改一個數據,可能造成很嚴重的後果。出現嚴重後果的原因是很多操作被操作系統編譯爲彙編代碼之後不止一條指令,因此在執行的時候可能執行了一半就被調度系統打斷了而去執行別的代碼了。一般將單指令的操作稱爲原子的(Atomic),因爲不管怎樣,單條指令的執行是不會被打斷的。
因此,爲了避免出現多線程操作數據的出現異常,Linux系統提供了一些常用操作的原子指令,確保了線程的安全。但是,它們只適用於比較簡單的場合,在複雜的情況下就要選用其他的方法了。
2. 同步與鎖
爲了避免多個線程同時讀寫一個數據而產生不可預料的後果,開發人員要將各個線程對同一個數據的訪問同步,也就是說,在一個線程訪問數據未結束的時候,其他線程不得對同一個數據進行訪問。
同步的最常用的方法是使用鎖(Lock),它是一種非強制機制,每個線程在訪問數據或資源之前首先試圖獲取鎖,並在訪問結束之後釋放鎖;在鎖已經被佔用的時候試圖獲取鎖時,線程會等待,直到鎖重新可用。
二元信號量是最簡單的一種鎖,它只有兩種狀態:佔用與非佔用,它適合只能被唯一一個線程獨佔訪問的資源。對於允許多個線程併發訪問的資源,要使用多元信號量(簡稱信號量)。
3. 可重入
一個函數被重入,表示這個函數沒有執行完成,但由於外部因素或內部因素,又一次進入該函數執行。一個函數稱爲可重入的,表明該函數被重入之後不會產生任何不良後果。可重入是併發安全的強力保障,一個可重入的函數可以在多線程環境下放心使用。
4. 過度優化
在很多情況下,即使我們合理地使用了鎖,也不一定能夠保證線程安全,因此,我們可能對代碼進行過度的優化以確保線程安全。

Synchronized如何使用
資料

synchronized是Java中的關鍵字,是一種同步鎖。它修飾的對象有以下幾種:
一. 修飾一個代碼塊,被修飾的代碼塊稱爲同步語句塊,其作用的範圍是大括號{}括起來的代碼,作用的對象是調用這個代碼塊的對象;
二. 修飾一個方法,被修飾的方法稱爲同步方法,其作用的範圍是整個方法,作用的對象是調用這個方法的對象;
三. 修改一個靜態的方法,其作用的範圍是整個靜態方法,作用的對象是這個類的所有對象;
四. 修改一個類,其作用的範圍是synchronized後面括號括起來的部分,作用主的對象是這個類的所有對象。

synchronized和Lock的區別
資料

主要相同點:Lock能完成synchronized所實現的所有功能
主要不同點:Lock有比synchronized更精確的線程語義和更好的性能。Lock的鎖定是通過代碼實現的,而synchronized是在JVM層面上實現的,synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,並且必須在finally從句中釋放。Lock還有更強大的功能,例如,它的tryLock方法可以非阻塞方式去拿鎖。Lock鎖的範圍有侷限性,塊範圍,而synchronized可以鎖住塊、對象、類。

多線程如何進行信息交互
資料

void notify() 喚醒在此對象監視器上等待的單個線程。 void notifyAll() 喚醒在此對象監視器上等待的所有線程。
void wait() 導致當前的線程等待,直到其他線程調用此對象的notify()方法或notifyAll()方法。 void
wait(long timeout)
導致當前的線程等待,直到其他線程調用此對象的notify()方法或notifyAll()方法,或者超過指定的時間量。 void
wait(long timeout, int nanos)
導致當前的線程等待,直到其他線程調用此對象的notify()方法或notifyAll()方法,或者其他某個線程中斷當前線程,或者已超過某個實際時間量。

sleep和wait的區別(考察的方向是是否會釋放鎖)
資料

sleep()方法是Thread類中方法,而wait()方法是Object類中的方法。
sleep()方法導致了程序暫停執行指定的時間,讓出cpu該其他線程,但是他的監控狀態依然保持着,當指定的時間到了又會自動恢復運行狀態,在調用sleep()方法的過程中,線程不會釋放對象鎖。而當調用wait()方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法後本線程才進入對象鎖定池準備

多線程與死鎖
資料

死鎖是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。 產生死鎖的原因:
一.因爲系統資源不足。 二.進程運行推進的順序不合適。 三.資源分配不當。

如何才能產生死鎖
資料

產生死鎖的四個必要條件: 一.互斥條件:所謂互斥就是進程在某一時間內獨佔資源。
二.請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。 三.不剝奪條件:進程已獲得資源,在末使用完之前,不能強行剝奪。
四.循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關係。

什麼叫守護線程,用什麼方法實現守護線程
資料

守護線程是爲其他線程的運行提供服務的線程。 setDaemon(boolean
on)方法可以方便的設置線程的Daemon模式,true爲守護模式,false爲用戶模式。

Java線程池技術及原理

java併發包concurrent及常用的類

volatile關鍵字

Java中的NIO,BIO,AIO分別是什麼

IO和NIO區別

序列化與反序列化

常見的序列化協議有哪些

內存溢出和內存泄漏的區別

Java內存模型及各個區域的OOM,如何重現OOM

出現OOM如何解決

用什麼工具可以查出內存泄漏

Java內存管理及回收算法

Java類加載器及如何加載類(雙親委派)

xml解析方式

Statement和PreparedStatement之間的區別

JavaEE:

servlet生命週期及各個方法

servlet中如何自定義filter

JSP原理

JSP和Servlet的區別

JSP的動態include和靜態include

Struts中請求處理過程

MVC概念

Spring mvc與Struts區別

Hibernate/Ibatis兩者的區別

Hibernate一級和二級緩存

Hibernate實現集羣部署

Hibernate如何實現聲明式事務

簡述Hibernate常見優化策略

Spring bean的加載過程(推薦看Spring的源碼)

Spring如何實現AOP和IOC

Spring bean注入方式

Spring的事務管理(推薦看Spring的源碼)

Spring事務的傳播特性

springmvc原理

springmvc用過哪些註解

Restful有幾種請求

Restful好處

Tomcat,Apache,JBoss的區別

memcached和redis的區別

有沒有遇到中文亂碼問題,如何解決的

如何理解分佈式鎖

你知道的開源協議有哪些

json和xml區別

設計模式:

設計模式的六大原則

常用的設計模式

用一個設計模式寫一段代碼或畫出一個設計模式的UML

如何理解MVC

高內聚,低耦合方面的理解

算法:

深度優先、廣度優先算法

排序算法及對應的時間複雜度和空間複雜度

寫一個排序算法

查找算法

B+樹和二叉樹查找時間複雜度

KMP算法、hash算法

常用的hash算法有哪些

如何判斷一個單鏈表是否有環?

給你一萬個數,如何找出裏面所有重複的數?用所有你能想到的方法,時間複雜度和空間複雜度分別是多少?

給你一個數組,如何裏面找到和爲K的兩個數?

100000個數找出最小或最大的10個?

一堆數字裏面繼續去重,要怎麼處理?

數據結構:

隊列、棧、鏈表、樹、堆、圖

編碼實現隊列、棧

Linux:

linux常用命令

如何查看內存使用情況

Linux下如何進行進程調度

操作系統:

操作系統什麼情況下會死鎖

產生死鎖的必要條件

死鎖預防

數據庫:

範式

數據庫事務隔離級別

數據庫連接池的原理

樂觀鎖和悲觀鎖

如何實現不同數據庫的數據查詢分頁

SQL注入的原理,如何預防

數據庫索引的實現(B+樹介紹、和B樹、R樹區別)

SQL性能優化

數據庫索引的優缺點以及什麼時候數據庫索引失效

Redis的存儲結構

網絡:

OSI七層模型以及TCP/IP四層模型

HTTP和HTTPS區別

HTTP報文內容

get提交和post提交的區別

get提交是否有字節限制,如果有是在哪限制的

TCP的三次握手和四次揮手

session和cookie的區別

HTTP請求中Session實現原理

redirect與forward區別

DNS

TCP和UDP區別

安全:

如果客戶端不斷的發送請求連接會怎樣

DDos攻擊

DDos預防

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章