遞歸方法:javascript
public Node reverse(Node head) { if (head == null || head.next == null) return head; Node temp = head.next; Node newHead = reverse(head.next); temp.next = head; head.next = null; return newHead; } //整體來講,遞歸法是從最後一個Node開始,在彈棧的過程當中將指針順序置換的。
遍歷方法:css
public static Node reverseList(Node node) { Node pre = null; Node next = null; while (node != null) { next = node.next; node.next = pre; pre = node; node = next; } return pre; } //先將下一節點紀錄下來,而後讓當前節點指向上一節點,再將當前節點紀錄下來,再讓下一節點變爲當前節點。
Java線程池詳解java
一、什麼是死鎖:死鎖是指多個進程因競爭資源而形成的一種僵局(互相等待),若無外力做用,這些進程都將沒法向前推動。node
二、死鎖的四個必要條件:redis
互斥條件:一個資源每次只能被一個進程使用,即在一段時間內某資源僅爲一個進程所佔有,此時如有其餘進程請求該資源,則請求進程只能等待;算法
請求與保持條件:進程已經保持了至少一個資源,但又提出了新的資源請求,而該資源已被其餘進程佔有,此時請求進程被阻塞,但對本身已得到的資源保持不放;數據庫
不可剝奪條件:進程所得到的資源在未使用完畢以前,不能被其餘進程強行奪走,即只能由得到該資源的進程本身來釋放(只能主動釋放);bootstrap
循環等待條件:若干進程間造成首尾相接循環等待資源的關係;segmentfault
這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不知足,就不會發生死鎖。
三、死鎖的避免:指定獲取鎖和釋放鎖的順序。
四、死鎖的預防:破壞致使死鎖的必要條件,使其不被知足。
四、Http1.0,Http1.1,Http2.0主要特性對比
五、http和https的區別:
(1)https協議須要到ca申請證書,通常免費證書較少,於是須要必定費用;
(2)http是超文本傳輸協議,信息是明文傳輸,https則是具備安全性的ssl加密傳輸協議;
(3)http和https使用的端口不一樣,前者是80,後者是443;
(4)http的鏈接很簡單,是無狀態的;https協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。
一、內存溢出:
是指程序在申請內存時,沒有足夠的內存空間供其使用,出現內存溢出,好比申請了一個integer,但給它存了long才能存下的數,那就是內存溢出;內存溢出就是你要求分配的內存超出了系統能給你的,系統不能知足需求,因而產生溢出。
二、內存泄漏:
是指程序在申請內存後,沒法釋放已申請的內存空間,一次內存泄漏危害能夠忽略,但內存泄漏堆積後果很嚴重,不管多少內存,早晚會被佔光,內存泄漏最終會致使內存溢出。內存泄漏是指你向系統申請分配內存進行使用,但是使用完了之後卻不歸還,結果你申請到的那塊內存你本身也不能再訪問,而系統也不能再次將它分配給須要的程序。
三、內存泄漏如何產生:
Java內存泄漏的根本緣由是長生命週期的對象持有短生命週期對象的引用就極可能發生內存泄漏,儘管短生命週期對象已經再也不須要,可是由於長生命週期持有它的引用而致使不能被回收,這就是Java中內存泄漏的發生場景。
HashMap基於哈希思想,實現對數據的讀寫,底層採用數組+鏈表實現,能夠存儲null鍵和null值,線程不安全:
一、同步:
同步就是發起一個請求,直到請求返回結果以後,才進行下一步操做;簡單來講,同步就是必須一件事一件事的作,等前一件作完了,才能作下一件事。
二、異步:
異步很明顯是與同步相對,兩者的區別在因而否須要等待某操做的返回結果;簡單來講,咱們仍是一個網絡請求,若是咱們此時不須要依賴這個請求的結果就能進行後續操做,那麼此時這個網絡請求就是一個異步操做。
三、同步阻塞:
效率最低,專心等待事情完成,什麼別的事都不作。
四、異步阻塞:
異步操做是能夠被阻塞的,只不過它不是在處理消息時阻塞,而是在等待消息通知時被阻塞。
五、同步非阻塞:
其實是效率低下的,一邊幹別的事情一邊還須要擡頭看上一件事完成沒有,若是把幹別的事情和觀察完成狀況當作是程序的兩個操做的話,這個程序須要在這兩種不一樣的行爲之間來回的切換,效率可想而知是低下的。
六、異步非阻塞:
效率更高,由於等待事情完成是等待者的事,而通知你則是消息觸發機制的事,程序沒有在這兩種不一樣的操做中來回切換。
一、簡介:
裝飾者模式經過組合的方式擴展對象的特性,這種方式容許咱們在任什麼時候候對對象的功能進行擴展甚至是運行時擴展,若咱們用繼承來完成對類的擴展則只能在編譯階段實現,因此在某些時候裝飾者模式比繼承要更加靈活。
二、裝飾者模式在jdk中的使用場景:
java.io包(BufferInputStream至關於一個裝飾器實現者,使得FilterInputStream讀取的數據能暫存在內存中,從減小I/O的角度提升了讀取效率)。
三、裝飾者模式簡單的業務使用場景:
咖啡店裏的咖啡加上不一樣的配料(牛奶、糖、奶泡)有不一樣的價錢,可使用裝飾者模式實現;首先定義一個咖啡基類,接着定義一個裝飾器類繼承咖啡基類,最後來實現添加配料的裝飾子類。
一、手寫單例模式實現:
//餓漢式 public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance(){ return instance; } } //懶漢式 public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance(){ if (instance == null) { instance = new Singleton(); } return instance; } }
首先單例類必需要有一個private訪問級別的構造函數,只有這樣,才能確保單例不會在系統中的其餘代碼內被實例化,這點是至關重要的;其次,singleton成員和getSingleton()方法必須是static的。
二、多線程中的懶漢式單例模式(synchronized方法級別鎖):
public class Singleton { private static Singleton instance;
private Singleton() { } public static synchronized Singleton getInstance(){ if (instance == null) { instance = new Singleton(); } return instance; } }
三、雙重鎖實現的單例模式:
public class Singleton { private volatile static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
雙重加鎖要對instance域加上volatile修飾符,synchronized並非對instance實例進行加鎖(由於如今還並無實例),因此線程在執行完instance = new Singleton()後,instance的值被修改,應該將修改後的instance當即寫入主存,而不是暫時存在寄存器或者高速緩衝區中,以保證新的值對其它線程可見。
四、靜態內部類實現的單例模式:
public class SingleTon{ private SingleTon(){ } private static class SingleTonHoler{ private static SingleTon instance = new SingleTon(); } public static SingleTon getInstance(){ return SingleTonHoler.instance; } }
外部類加載時並不須要當即加載內部類,內部類不被加載則不去初始化instance,故而不佔內存,即當SingleTon第一次被加載時,並不須要去加載SingleTonHoler,只有當getInstance()方法第一次被調用時,纔會去初始化instance,第一次調用getInstance()方法會致使虛擬機加載SingleTonHoler類,這種方法不只能確保線程安全,也能保證單例的惟一性,同時也延遲了單例的實例化。
一、redis實現分佈式鎖:
使用redis命令 set key value NX EX max-lock-time 實現加鎖
使用redis命令 EVAL 實現解鎖
二、redis的兩種持久化方式:
一、儲存引擎選擇,若是數據表須要事務處理,應該考慮使用InnoDB, 由於它完成兼容ACID特性(即事務的四大特性),若是不須要事務處理,使用默認儲存引擎MyISAM。
二、對查詢進行優化,儘可能避免全表掃描,能夠考慮在where及order by涉及的列上創建索引。
三、應儘可能避免在where子句中對字段進行null值判斷,不然將導則引擎放棄使用索引而進行全表掃描。
四、對於多張大數據量表的JOIN,要先分頁再JOIN,不然邏輯讀會很高,性能差。
一、SSL:
SSL(安全套接層)是TCP/IP協議中基於HTTP之下TCP之上的一個可選協議層;起初HTTP在傳輸數據時使用的是明文,是不安全的,爲了解決這個隱患,網景公司推出了SSL,愈來愈多的人也開始使用HTTPS(HTTP+SSL)。
二、TLS:
SSL更新到3.0時,互聯網工程任務組將其改名爲TLS1.0(安全傳輸層協議),TLS也就是SSL的新版本3.1。
三、區別:
(1)SSL與TLS二者所使用的算法是不一樣的
(2)TLS增長了許多新的報警代碼,好比解密失敗、拒絕訪問等,但同時也支持SSL協議上全部的報警代碼
一、TCP:可靠、面向鏈接、面向字節流、傳輸效率低
二、UDP:不可靠、無鏈接、面向報文、傳輸效率高
三、TCP應用場景:
當對網絡通訊質量要求高的時候,好比整個數據要準確無誤的傳遞給對方,這時就使用TCP,好比瀏覽器使用的HHTP協議、QQ文件傳輸。
四、UDP應用場景:
當對網絡通信質量要求不高的時候,要求網絡通信速度儘可能的快,這時就使用UDP,好比QQ語音、QQ視頻。
管道、消息隊列、信號量、共享內存。
線程上下文、共享內存、Socket套接字(不一樣的機器之間進行通訊)。
Redis是內存數據庫,數據保存在內存中,訪問速度快;
MySQL是關係型數據庫,功能強大,存儲在磁盤中,數據訪問速度慢。
一、MySQL只有Innodb引擎支持數據庫的事務操做,事務是一條或多條數據庫操做的集合,在事務中的操做,要麼都執行修改,要麼都不執行,MySQL事務具備原子性、一致性、隔離性、持久性(ACID)。
二、事務的隔離級別:
未提交讀:事務中的修改,即便沒有提交,在其餘事務也都是可見的;事務能夠讀取未提交的數據,這也被稱爲髒讀。
提交讀:一個事務從開始直到提交以前,所作的任何修改對其餘事務都是不可見的;這個級別有時候也叫作不可重複讀,由於兩次執行相同的查詢,可能會獲得不同的結果,由於在這兩次讀之間可能有其餘事務更改這個數據,每次讀到的數據都是已經提交的。
可重複讀:解決了髒讀,也保證了在同一個事務中屢次讀取一樣記錄的結果是一致的;可重複讀隔離級別仍是沒法解決另一個幻讀的問題,指的是當某個事務在讀取某個範圍內的記錄時,另一個事務也在該範圍內插入了新的記錄,當以前的事務再次讀取該範圍內的記錄時,會產生幻行。
可串行化:經過強制事務串行執行,避免了前面說的幻讀的問題,但因爲讀取的每行數據都加鎖,會致使大量的鎖徵用問題,所以性能也最差。
經過哈希算法,將40億個qq號按照哈希值散落到多個文件中,重複的qq號有相同的哈希值,確定位於一個文件中,這樣就能夠分別對每一個文件排序刪除重複的qq號。
DNS域名解析 –>
發起TCP的三次握手 –>
創建TCP鏈接後發起http請求 –>
服務器響應http請求,瀏覽器獲得html代碼 –>
瀏覽器解析html代碼,並請求html代碼中的資源(如javascript、css、圖片等) –>
瀏覽器對頁面進行渲染呈現給用戶。
(1)cookie經過在客戶端記錄信息肯定用戶身份,session經過在服務器端記錄信息肯定用戶身份;
(2)cookie數據存放在客戶的瀏覽器上,session數據存放在服務器上;
(3)cookie不是很安全,他人能夠分析存放在本地的cookie進行cookie欺騙,而session較爲安全,考慮安全問題應當使用session;
(4)session會在必定時間內保存在服務器上,當服務器的訪問量增多時,會佔用服務器的內存,考慮減輕服務器負載的問題,應該使用cookie;
cpu平均負載是指某段時間內佔用cpu時間的進程和等待cpu時間的進程數,這裏等待cpu時間的進程是指等待被喚醒的進程,不包括處於wait狀態進程。
在命令窗口中輸入 ipconfig 便可查看。
第一次握手:客戶端發送一個帶SYN的報文到服務器端,表示客戶端想要和服務器端創建鏈接;
第二次握手:服務器端接收到客戶端的請求,返回客戶端報文,這個報文帶有SYN和ACK確認標識;
第三次握手:客戶端再次響應服務端一個ACK確認,表示已經準備好了。
第一次揮手:客戶端發送一個FIN,關閉客戶端到服務器端的鏈接;
第二次揮手:服務器端收到這個FIN後發回一個ACK確認標識,確認收到;
第三次揮手:服務器端發送一個FIN到客戶端,服務器端關閉客戶端的鏈接;
第四次揮手:客戶端發送ACK報文確認,這樣關閉完成。
類加載過程包括加載、驗證、準備、解析和初始化五個階段。
一、java類加載器的種類:
引導類加載器(bootstrap classloader);
擴展類加載器(extensions classloader);
應用程序類加載器(application classloader);
自定義類加載器(java.lang.classloder)。
二、類加載器之間的關係:
啓動類加載器,由C++實現,沒有父類;
拓展類加載器,由Java語言實現,父類加載器爲null;
系統類加載器,由Java語言實現,父類加載器爲拓展類加載器;
自定義類加載器,父類加載器確定爲系統類加載器。
三、雙親委派機制工做原理:
若是一個類加載器收到了類加載請求,它並不會本身先去加載,而是把這個請求委託給父類的加載器去執行,若是父類加載器還存在其父類加載器,則進一步向上委託,依次遞歸,請求最終將到達頂層的啓動類加載器,若是父類加載器能夠完成類加載任務,就成功返回,假若父類加載器沒法完成此加載任務,子加載器纔會嘗試本身去加載,這就是雙親委派模式,即每一個兒子都很懶,每次有活就丟給父親去幹,直到父親說這件事我也幹不了時,兒子本身想辦法去完成。
四、雙親委派機制的做用:
經過這種層級關能夠避免類的重複加載,當父親已經加載了該類時,就沒有必要讓子類加載器再加載一次;其次是考慮到安全因素,java核心api中定義的類型不會被隨意替換。
第一次建立Session的時候,服務端會在HTTP協議中告訴客戶端,須要在 Cookie 裏面記錄一個Session ID,之後每次請求把這個會話ID發送到服務器,就能知道是哪一個用戶了。
在某段時間內,對網絡中某一資源的需求超過了該資源所能提供的可用部分,網絡的性能就要變壞,這種狀況就稱爲擁塞,簡單的說擁塞產生的緣由有兩點:接收方容量不夠、網絡內部有瓶頸。
TCP進行擁塞控制的四種算法:慢啓動、擁塞避免、快速重傳、快速恢復。