JAVA部分:html
Stream 是 Java8 中處理集合的關鍵抽象概念,它能夠指定你但願對集合進行的操做,能夠執行很是複雜的查找、過濾和映射數據等操做。使用Stream API 對集合數據進行操做,就相似於使用 SQL 執行的數據庫查詢。也可使用 Stream API 來並行執行操做。簡單來講,Stream API 提供了一種高效且易於使用的處理數據的方式。java
線程: 每一個進程中至少包含一個線程,而這些線程都在共享進程的資源空間等,當線程發生變化的時候只會引發CPU執行的過程發生變化,不會改變進程所擁有的資源。進程中執行運算的最小單位,亦是執行處理機調度的基本單位程序員
進程: 每一個進程都有本身的地址空間,資源如,內存,I/O,CPU,同一個進程裏的 線程共享本進程裏的地址空間,那能不能使用別人家進程的地址空間呢,顯然這是不能夠的。算法
1. 管道(PIPE) 管道是一種半雙工的通訊方式,數據只能單向流動,並且只能在具備親緣關係的進程間使用。進程的親緣關係一般是指父子進程關係。 2. 命名管道(FIFO) 名管道也是半雙工的通訊方式,可是它容許無親緣關係進程間的通訊。 3. 信號(Signal) 用於通知接收進程某個事件已經發生,主要做爲進程間以及同一進程不一樣線程之間的同步手段。 4. 信號量(Semaphore) 信號量是一個計數器,能夠用來控制多個進程對共享資源的訪問。它常做爲一種鎖機制,防止某進程正在訪問共享資源時,其餘進程也訪問該資源。 5. 消息隊列(MessageQueue) 消息隊列是消息的鏈表,存放在內核中。一個消息隊列由一個標識符(即隊列ID)來標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩衝區大小受限等缺點。 6. 共享內存(Shared Memory) 共享內存(Shared Memory),指兩個或多個進程共享一個給定的存儲區。 特色: 共享內存是最快的一種 IPC,由於進程是直接對內存進行存取。 由於多個進程能夠同時操做,因此須要進行同步。 信號量+共享內存一般結合在一塊兒使用,信號量用來同步對共享內存的訪問。 7. 套接字(Socket) 套接字也是一種進程間通訊機制,與其餘通訊機制不一樣的是,它可用於不一樣機器間的進程通訊sql
1、傳統線程通訊synchronized + wait + notify編程
Object類的wait()、notify() 、notifyAll()三個方法必須由同步監視器對象來調用,分兩種狀況:設計模式
a)同步方法,該類默認實例(this)就是同步監視器,能夠在同步方法中能夠直接調用數組
b)同步代碼塊,同步監視器是synchronized後括號裏的對象,因此必須使用此對象調用這三個方法緩存
2、使用Condition控制線程通訊lock + condition + await + signal
Lock代替同步方法或同步代碼塊,Condition替代同步監視器的功能。
private final Lock lock = newReentrantLock();
private final Condition con =lock.newCondition();
lock.lock(); con.await(); con.signalAll(); lock.unlock():
3、使用阻塞隊列(BlockingQueue)控制線程通訊
BlockingQueue接口主要做爲線程同步的工具。當生產者試圖向BlockingQueue中放入元素,若是隊列已滿,則線程被阻塞;當消費者試圖向BlockingQueue中取出元素時,若該隊列已空,則線程被阻塞。
答:
鏈表與數組的主要區別:
(1)數組的元素個數是固定的,而組成鏈表的結點個數可按須要增減;
(2)數組元素的存儲單元在數組定義時分配,鏈表結點的存儲單元在程序執行時動態向系統申請:
(3)數組中的元素順序關係由元素在數組中的位置(即下標)肯定,鏈表中的結點順序關係由結點所包含的指針來體現。
(4)對於不是固定長度的列表,用可能最大長度的數組來描述,會浪費許多內存空間。
(5)對於元素的插人、刪除操做很是頻繁的列表處理場合,用數組表示列表也是不適宜的。若用鏈表實現,會使程序結構清晰,處理的方法也較爲簡便。
鏈表與數組的聯繫:
ArrayList數組和LinkedList鏈表都是不一樣步的,也就是不保證線程安全。
從邏輯結構來看
數組必須事先定義固定的長度(元素個數),不能適應數據動態地增減的狀況。當數據增長時,可能超出原先定義的元素個數;當數據減小時,形成內存浪費;數組能夠根據下標直接存取。
鏈表動態地進行存儲分配,能夠適應數據動態地增減的狀況,且能夠方便地插入、刪除數據項。(數組中插入、刪除數據項時,須要移動其它數據項,很是繁瑣)鏈表必須根據next指針找到下一個元素
從內存存儲來看
(靜態)數組從棧中分配空間, 對於程序員方便快速,可是自由度小
鏈表從堆中分配空間, 自由度大可是申請管理比較麻煩
從上面的比較能夠看出,若是須要快速訪問數據,不多或不插入和刪除元素,就應該用數組;相反, 若是須要常常插入和刪除元素就須要用鏈表數據結構了。
答:
1、線程安全在三個方面體現
1.原子性:提供互斥訪問,同一時刻只能有一個線程對數據進行操做,(atomic,synchronized);
2.可見性:一個線程對主內存的修改能夠及時地被其餘線程看到,(synchronized,volatile);
3.有序性:一個線程觀察其餘線程中的指令執行順序,因爲指令重排序,該觀察結果通常雜亂無序,(happens-before原則)。 解決方法:
對非安全的代碼進行加鎖控制;
使用線程安全的類;
多線程併發狀況下,線程共享的變量改成方法級的局部變量。
一、同步方法
synchronized關鍵字修飾方法。因爲java的每一個對象都有一個內置鎖,當用此關鍵字修飾方法時,內置鎖會保護整個方法。在調用該方法前,須要得到內置鎖,不然就處於阻塞狀態。
二、同步代碼塊
synchronized關鍵字修飾的語句塊。被該關鍵字修飾的語句塊會自動加上內置鎖,從而實現同步
三、使用特殊域變量(volatile)實現線程同步
a.volatile關鍵字爲域變量的訪問提供一種免鎖機制
b.使用volatile修飾域至關於告訴虛擬機該域可能被其餘現象更新
c.所以每次使用該域就要從新計算,而不是使用寄存器中的值
d.volatile不會提供任何原子操做,它也不能用來修飾final類型的變量
4:使用重入鎖實現線程同步
在javaSE5.0新增了一個java.concurrent包來支持同步。ReentrantLock類能夠重入、互斥、實現了Lock接口的鎖,它與使用synchronized方法和快具體相同的基本行爲和語義,而且擴展了其能力
5.使用局部變量實現線程同步
若是使用ThreadLocal管理變量,則每個使用變量的線程都得到該變量的副本,副本之間相互獨立,這樣每個線程均可以隨意修改本身的變量副本,而不會對其餘線程產生影響。
1.自定義線程池
繼承Thread類
實現Runnable接口
實現Callable接口
線程池:提供了一個線程隊列,隊列中保存着全部等待狀態的線程。避免了建立與銷燬額外開銷,提升了響應的速度。
1.繼承Thread類實現多線程
2.覆寫Runnable()接口實現多線程,然後一樣覆寫run().推薦此方式
3.覆寫Callable接口實現多線程(JDK1.5)
4.經過線程池啓動多線程
1.單個任務處理的時間比較短 2.將需處理的任務的數量大
線程池作的工做主要是控制運行的線程的數量,處理過程當中將任務放入隊列,而後在線程建立後啓動這些任務,若是線程數量超過了最大數量超出數量的線程排隊等待,等其它線程執行完畢,再從隊列中取出任務來執行。
線程池由任務隊列和工做線程組成,它能夠重用線程來避免線程建立的開銷,在任務過多時經過排隊避免建立過多線程來減小系統資源消耗和競爭,確保任務有序完成
ThreadPoolExecutor 繼承自 AbstractExecutorService 實現了 ExecutorService 接口,ScheduledThreadPoolExecutor 繼承自 ThreadPoolExecutor 實現了 ExecutorService 和 ScheduledExecutorService 接口
實現原理: JVM 是經過進入、退出 對象監視器(Monitor) 來實現對方法、同步塊的同步的,而對象監視器的本質依賴於底層操做系統的 互斥鎖(Mutex Lock) 實現。
具體實現是在編譯以後在同步方法調用前加入一個monitor.enter
指令,在退出方法和異常處插入monitor.exit
的指令。
對於沒有獲取到鎖的線程將會阻塞到方法入口處,直到獲取鎖的線程monitor.exit
以後才能嘗試繼續獲取鎖。
1.目的: 爲何要上鎖,主要仍是多線程的緣由。多線程可能對同一塊數據同時操做,數據可能會異常,好比,一個map,A線程把對鍵值對刪除,B線程讀取鍵值對,而後段錯誤就產生了。
被synchronized修飾的代碼段能夠防止被多個線程同時執行,必須一個線程把synchronized修飾的代碼段都執行完畢了,其餘的線程才能開始執行這段代碼。
volatile關鍵字的做用就是保證了可見性和有序性(不保證原子性),若是一個共享變量被volatile關鍵字修飾,那麼若是一個線程修改了這個共享變量後,其餘線程是立馬可知的。
synchronized 多用於在多個線程中須要對同一段數據進行訪問時候,出現的不安全狀況。由於多個線程執行同一段代碼會形成數據不安全,因此須要用synchronized來同步代碼。
一、可重入性:
從名字上理解, ReenTrantLock的字面意思就是再進入的鎖,其實synchronized關鍵字所使用的鎖也是可重入的,二者關於這個的區別不大。二者都是同一個線程每進入一次,鎖的計數器都自增1,因此要等到鎖的計數器降低爲0時才能釋放鎖。
二、鎖的實現:
Synchronized是依賴於JVM實現的,而ReenTrantLock是JDK實現的,有什麼區別,說白了就相似於操做系統來控制實現和用戶本身敲代碼實現的區別。前者的實現是比較難見到的,後者有直接的源碼可供閱讀。
三、性能的區別:
在Synchronized優化之前,synchronized的性能是比ReenTrantLock差不少的,可是自從Synchronized引入了偏向鎖,輕量級鎖(自旋鎖)後,二者的性能就差很少了,在兩種方法均可用的狀況下,官方甚至建議使用synchronized,其實synchronized的優化我感受就借鑑了ReenTrantLock中的CAS技術。都是試圖在用戶態就把加鎖問題解決,避免進入內核態的線程阻塞。
四、功能區別:
便利性:很明顯Synchronized的使用比較方便簡潔,而且由編譯器去保證鎖的加鎖和釋放,而ReenTrantLock須要手工聲明來加鎖和釋放鎖,爲了不忘記手工釋放鎖形成死鎖,因此最好在finally中聲明釋放鎖。
五、鎖的細粒度和靈活度:
很明顯ReenTrantLock優於Synchronized
答:
兩個線程會依次執行,說明產生互斥,由於實例方法加鎖針對的是實例對象,當前對象調用一個synchronized方法時,其餘同步方法須要等待其執行結束並釋放鎖以後才能執行。
兩個/多個線程佔有鎖的前提又去得到其餘鎖,這樣形成的線程無限的循環等待,產生了死鎖!
答:
答:
Java 集合類型分爲 Collection 和 Map,它們是 Java 集合的根接口,這兩個接口又包含了一些子接口或實現類。
答:
**1.**從結構實現來說,HashMap是數組+鏈表+紅黑樹(鏈表長度大於8時轉換成紅黑樹,小於6時變爲單項鍊表)(JDK1.8增長了紅黑樹部分)實現的
2. map.put(k,v)實現原理:
第一步:首先將k,v封裝到Node對象當中(節點)。
第二步:它的底層會調用K的hashCode()方法得出hash值。
**第三步:**經過哈希表函數/哈希算法,將hash值轉換成數組的下標,下標位置上若是沒有任何元素,就把Node添加到這個位置上。若是說下標對應的位置上有鏈表。此時,就會拿着k和鏈表上每一個節點的k進行equal。若是全部的equals方法返回都是false,那麼這個新的節點將被添加到鏈表的末尾。如其中有一個equals返回了true,那麼這個節點的value將會被覆蓋。
3. map.get(k)實現原理:
**第一步:**先調用k的hashCode()方法得出哈希值,並經過哈希算法轉換成數組的下標。
**第二步:**經過上一步哈希算法轉換成數組的下標以後,在經過數組下標快速定位到某個位置上。重點理解若是這個位置上什麼都沒有,則返回null。若是這個位置上有單向鏈表,那麼它就會拿着參數K和單向鏈表上的每個節點的K進行equals,若是全部equals方法都返回false,則get方法返回null。若是其中一個節點的K和參數K進行equals返回true,那麼此時該節點的value就是咱們要找的value了,get方法最終返回這個要找的value。
由於equals默認比較是兩個對象內存地址
HashMap默認的「加載因子」是0.75,默認的容量大小是16;增長容量時,每次將容量變爲「原始容量x2」。
Hashtable 也是一個散列表,它存儲的內容是鍵值對(key-value)映射。Hashtable 的函數都是同步的,這意味着它是線程安全的。它的key、value都不能夠爲null。此外,Hashtable中的映射不是有序的。
1 繼承和實現方式不一樣
HashMap 繼承於AbstractMap,實現了Map、Cloneable、java.io.Serializable接口。 Hashtable 繼承於Dictionary,實現了Map、Cloneable、java.io.Serializable接口。
2 線程安全不一樣
Hashtable的幾乎全部函數都是同步的,即它是線程安全的,支持多線程。 而HashMap的函數則是非同步的,它不是線程安全的。
3 對null值的處理不一樣
HashMap的key、value均可覺得null。 Hashtable的key、value都不能夠爲null。
4 遍歷方式不一樣
HashMap只支持Iterator(迭代器)遍歷。此種迭代方式,HashMap是「從前向後」的遍歷數組;Hashtabl是「從後往前」的遍歷數組;而Hashtable支持Iterator(迭代器)和Enumeration(枚舉器)兩種方式遍歷。
5 添加元素時的hash值算法不一樣
HashMap添加元素時,是使用自定義的哈希算法。
Hashtable沒有自定義哈希算法,而直接採用的key的hashCode()。
6 容量的初始值和增長方式不同
HashMap默認的「加載因子」是0.75,默認的容量大小是16;增長容量時,每次將容量變爲「原始容量x2」。 Hashtable默認的「加載因子」是0.75,默認的容量大小是11;增長容量時,每次將容量變爲「原始容量x2 + 1」。
HashMap不是線程安全的;而ConcurrentHashMap 是線程安全的,可是效率有點慢
不是線程安全的;
一、繼承HashMap,重寫或者按要求編寫本身的方法,這些方法要寫成synchronized,在這些synchronized的方法中調用HashMap的方法 二、使用Collections.synchronizedMap() 三、使用ConcurrentHashMap替代,並不推薦新代碼使用Hashtable,HashTable繼承於Dictionary,任意時間只有一個線程能寫Hashtable,併發性能不如ConcurrentHashMap,由於ConcurrentHashMap引入了分段鎖。不須要線程安全的場景使用HashMap,須要線程安全的場合使用ConcurrentHashMap替換。
大體區別:
1.ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。 (LinkedList是雙向鏈表,有next也有previous)
2.對於隨機訪問get和set,ArrayList以爲優於LinkedList,由於LinkedList要移動指針。
3.對於新增和刪除操做add和remove,LinedList比較佔優點,由於ArrayList要移動數據。
Vector:就比Arraylist多了個同步化機制(線程安全)。
Hashtable:就比Hashmap多了個線程安全。
ConcurrentHashMap:是一種高效可是線程安全的集合。
Stack:棧,也是線程安全的,繼承於Vector。
Vector(白客特)、HashTable、Properties是線程安全的;
ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等都是線程不安全的。
Vector(白客特)
根據JVM規範,JVM 內存共分爲五類:虛擬機棧,堆,方法區,程序計數器,本地方法棧五個部分。
內存區域是指 Jvm 運行時將數據分區域存儲。
整個生命週期包括:加載(Loading)、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Useing)、卸載(Unloading)7個階段。其中驗證、準備和解析3個部分統稱爲鏈接(Linking),
加載
「加載」是「類加載」過程的一個階段,由類加載器來完成,主要作如下3件事:
驗證
驗證是鏈接階段的第一步,這一階段的目的是爲了確保Class文件的二進制字節流中包含的信息符合當前虛擬機的要求,而且不會危害虛擬機自身的安全。
主要進行以下4個驗證:
準備
準備階段是正式爲類變量分配內存並設置類變量初始值的階段, 這些變量所使用的內存都將在方法區中進行分配。
解析
解析階段是虛擬機將常量池內的符號引用替換爲直接引用的過程
初始化
類初始化階段是類加載過程的最後一步,在這一階段纔開始執行類中定義的Java代碼(字節碼)。初始化階段是執行類構造器 ()方法(類構造器就是「類變量的賦值動做+靜態語句塊」)的過程。
JVM 內存共分爲五類:虛擬機棧,堆,方法區,程序計數器,本地方法棧五個部分。其中程序計數器、虛擬機棧、本地方法棧3個區域隨線程而生、隨線程而滅,所以這幾個區域的內存分配和回收都具有肯定性,就不須要過多考慮回收的問題,由於方法結束或者線程結束時,內存天然就跟隨着回收了。而Java堆區和方法區則不同、不同!(怎麼不同說的朗朗上口),這部份內存的分配和回收是動態的,正是垃圾收集器所需關注的部分。
Java中標記垃圾的算法主要有兩種, 引用計數法和可達性分析算法。
引用計數法:
引用計數法就是給對象中添加一個引用計數器,每當有一個地方引用它,計數器就加 1;當引用失效,計數器就減 1;任什麼時候候計數器爲 0 的對象就是不可能再被使用的,能夠當作垃圾收集。
可達性分析算法:
這個算法的基本思想就是經過一系列的稱爲 「GC Roots」 的對象做爲起點,從這些節點開始向下搜索,節點所走過的路徑稱爲引用鏈,當一個對象到 GC Roots 沒有任何引用鏈相連的話,則證實此對象是不可用的。
Java中存在着四種垃圾回收算法,標記清除算法、複製算法、標記整理算法以及分代回收算法。
1.標記清除算法
該算法分爲「標記」和「清除」兩個階段:標記階段的任務是標記出全部須要被回收的對象,清除階段就是回收被標記的對象所佔用的空間。它是最基礎的收集算法
2.複製算法
爲了解決效率問題,咱們開發出了複製算法。它能夠將內存分爲大小相同的兩塊,每次使用其中的一塊。當第一塊的內存使用完後,就將還存活的對象複製到另外一塊去,而後再把使用的空間一次清理掉。這樣就使每次的內存回收都是對內存區間的一半進行回收。
簡單來講就是該對象分爲對象面以及空閒面,對象在對象面上建立,對象面上存活的對象會被複制到空閒面,接下來就能夠清除對象面的內存。
3.標記整理算法
爲了解決複製算法的缺陷,充分利用內存空間,提出了標記整理算法。該算法標記階段和標記清除同樣,可是在完成標記以後,它不是直接清理可回收對象,而是將存活對象都向一端移動,而後清理掉端邊界之外的內存。
4.分代收集算法
當前虛擬機的垃圾收集都採用分代收集算法,這種算法就是根據具體的狀況選擇具體的垃圾回收算法。通常將 java 堆分爲新生代和老年代,這樣咱們就能夠根據各個年代的特色選擇合適的垃圾收集算法。
**答:**由於 StringBuffer 的全部公開方法都是 synchronized 修飾的
**答:區別1:**StringBuffer:線程安全,StringBuilder:線程不安全。由於 StringBuffer 的全部公開方法都是 synchronized 修飾的,而 StringBuilder 並無 synchronized修飾。
**區別2:**緩衝區 StringBuffer 每次獲取 toString 都會直接使用緩存區的 toStringCache 值來構造一個字符串。而 StringBuilder 則每次都須要複製一次字符數組,再構造一個字符串。因此,緩存衝這也是對 StringBuffer 的一個優化吧,不過 StringBuffer 的這個toString 方法仍然是同步的。
**區別3:**既然 StringBuffer 是線程安全的,它的全部公開方法都是同步的,StringBuilder 是沒有對方法加鎖同步的,因此毫無疑問,StringBuilder 的性能要遠大於 StringBuffer。
所謂的反射機制就是java語言在運行時擁有一項自觀的能力。經過這種能力能夠完全的瞭解自身的狀況爲下一步的動做作準備。
Java的反射機制的實現要藉助於4個類:class,Constructor,Field,Method。
Java反射的做用:在Java運行時環境中,對於任意一個類,能夠知道這個類有哪些屬性和方法。對於任意一個對象,能夠調用它的任意一個方法。這種動態獲取類的信息以及動態調用對象的方法的功能來自於Java 語言的反射(Reflection)機制。
序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。能夠對流化後的對象進行讀寫操做,也可將流化後的對象傳輸於網絡之間。
一、抽象類能夠提供某些方法的部分實現,而接口不能夠;
二、抽象類是單個繼承機制,其子類不必定要實現父類中的全部沒實現的方法,而接口一個類能夠有多個接口,而且方法都要實現。
冒泡排序、快速排序
最根本的區別在因而否真正獲取一個對象的複製實體,而不是引用
深拷貝(deepCopy)是增長了一個指針而且申請了一個新的內存,使這個增長的指針指向這個新的內存,
能夠對程序做出解釋,方便被其餘程序(編輯器)讀取
MD5
不可逆的
不能夠,覆蓋(override)是在繼承+多態的前提下的概念。Java中的靜態方法很少態,因此不涉及覆蓋,不管靜態方法是在基類仍是派生類上。
封裝的概念
封裝性是面向對象編程的核心思想
指的就是將描述某種實體的數據和基於這些數的操做集合到一塊兒,造成一個封裝體
封裝的思想保證了類內部數據結構的完整性,使用戶沒法輕易直接操做類的內部數據,這樣下降了對內部數據的影響,提升了程序的安全性和可維護性。
繼承的概念
繼承是Java面向對象編程技術的一塊基石,由於它容許建立分等級層次的類。
繼承就是子類繼承父類的特徵和行爲,使得子類對象(實例)具備父類的實例域和方法,或類從父 類繼承方法,使得子類具備父類相同的行爲。
多態的概念
多態指的就是在應用程序中出現的「 重名 」 現象。多態性容許以統一的風格編寫程序,以處理種類繁多的已存在的類及其相關類。這樣既下降了維護難度,又節省了時間
建立者模式又叫建造者模式,是將一個複雜的對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。建立者模式隱藏了複雜對象的建立過程,它把複雜對象的建立過程加以抽象,經過子類繼承或者重載的方式,動態的建立具備複合屬性的對象。
在用戶不知道對象的建造過程和細節的狀況下就能夠直接建立複雜的對象。
方便用戶建立複雜的對象(不須要知道實現過程)
代碼複用性 & 封裝性(將對象構建過程和細節進行封裝 & 複用)
1.普通索引index :加速查找 2.惟一索引 主鍵索引:primary key :加速查找+約束(不爲空且惟一) 惟一索引:unique:加速查找+約束 (惟一) 3.聯合索引 -primary key(id,name):聯合主鍵索引 -unique(id,name):聯合惟一索引 -index(id,name):聯合普通索引 4.全文索引fulltext :用於搜索很長一篇文章的時候,效果最好。 5.空間索引spatial :瞭解就好,幾乎不用
(頻繁改動和刪除的數據、數據量小、區分度小的字段(好比性別))
(不知足最左前綴原則、where 後面不能用函數)