java 鎖的補充:html
ReadWriteLock (ReadLock / WriteLock)
-> ReentrantReadWriteLock (同一線程對鎖的重複獲取)前端
寫鎖的降級 / 讀鎖的升級java
公平鎖 / 非公平鎖(synchronized使用非公平) (公平鎖維護隊列,效率低)mysql
自旋鎖 (在 while 循環中一直判斷某個條件,直到經過條件時才進入下個臨界)linux
===============================nginx
volatile 不加時怎麼通知另外一個線程讀取刷新的數據
兩個線程 (這個問題應該是從 JMM 的方面去回答)git
問題的答案 :
JMM決定一個線程對共享變量的寫入什麼時候對另外一個線程可見github
JMM是什麼的問題:
JMM 就是 線程保存的本地變量副本和主內存之間進程通訊的機制, 能夠適當涉及到 happens-before/volatile/synchronized/重排序方面的知識
happen-before : 講一下傳遞性, 鎖的解鎖 happens-before 的加鎖web
問題解決 --> https://segmentfault.com/a/1190000009828216
JMM模型
==============================面試
jvm 的各個區域的做用 (http://www.jianshu.com/p/54eb60cfa7bd)
共享:
方法區 :被加載的類信息、常量、靜態變量 (代碼存放編譯完成後的信息)
堆 :存放對象實例、數組
線程私有:
虛擬機棧 :基本數據類型的數據,以及對象的引用
本地方法棧 :(native方法)
線程計數器 :執行字節碼指示器,指示下一個執行的指令
StackOverflow 和 OutofMemory 的區別
若是線程須要的空間大於容許值,則爲StackOverflowError;若是stack空間能夠動態增長,但最後內存仍是不夠,則爲OutOfMemoryError。
每個JVM線程維護本身的JVM stack. JVM stack裏面存放 JVM棧幀. 棧幀中存放 數據和中間結果(本地變量數組, 操做符棧, 和對runtime 常量池的引用). 這些數據都比較小(對象都在堆中, 棧幀僅存放對象引用), 因此想單純經過 在棧幀中存放大數據的方法 去引入StackOverflowError, 基本是不現實的.通常都是由於方法調用嵌套層數過大.
(不斷建立對象(位於堆中) -> OutofMemory )
==============================
ConcurrentHashMap:
Segment數組 (可重入鎖)
HashEntry數組 (存儲鍵值對) -》 修改HashEntry裏的元素,須要獲取對應的Segment鎖
join : 是當前線程等待join線程執行完成以後再繼續執行
CountDownLatch 等待N個點完成(構造器中傳入的參數N)
countdown 方法減小計數器的值
await 方法阻塞當前線程 (有超時等待的版本)
CyclicBarrier 阻塞線程到同步點,知道全部的線程都到達同步點時才繼續 (線程調用await方法通知到達同步點)
Semaphore 控制同時訪問特定資源的線程數 (acquire方法獲取, release方法釋放)
線程池: Executor框架
FixedThreadPool 固定線程數量 LinkedBlockingQueue(無界隊列)
SigleThreadExecutor 當個worker的池 LinkedBlockingQueue(無界隊列)
CachedThreadPool 根據須要建立新線程的線程池 沒有容量的SynchronousQueue(每一個插入操做必須等待另外一個線程的移除操做)
ScheduledThreadPoolExecutor extends ThreadPoolExecutor 能夠指定多個對應的後臺線程數
==============================
FutureTask Future
表明異步計算的結果 get方法在FutureTask完成阻塞,完成以後獲取結果或者返回異常
實現:
AQS 同步框架, 裏面封裝了 CAS 相似的方法, 維護了一個阻塞隊列, 位於頭部的隊列在執行完成以後通知以後的線程執行
Future:
定義一個泛型類,做爲get方法的返回值, get方法執行了實現了callable接口的線程,callable接口定義了一個泛型類,
做爲實現方法call的返回值類型 Runnable類的run方法沒有返回值
FutureTask
結合了Runnable和Future接口
get方法用於獲取執行任務的結果
run方法用於執行任務
Semaphore:(信號)
經過內部計數器控制一組線程在同一時間對某一資源的訪問
acquire方法使計數器值遞減
release方法使計數器值遞增
CountDownLatch:
經過內部計數器控制全部線程線程處於等待(經過CountDownLatch.await()),直到計數器值歸零後,全部任務一塊兒執行
後續任務
1,資源初始化前,使用該資源的線程等待
2,釋放服務前,依賴該線程的任務完成
3,多人遊戲前,全部參與者終端的鏈接
CyclicBarrier:
(一)經過內部計數器控制全部線程相互等待,直到公共路障點(Common Barrier Point)
(二)當await方法使計數器遞增數量到設定數量後,被await阻塞的方法繼續執行
BlockingQueue:(最阻塞隊列) 定義一些增刪該查的方法,實現對多線程狀況下 的處理
(筆試有遇過實現本身的BlockingQueue, 使用ReentrentLock,lock.await() lock.signal() 實現
參考 http://www.jb51.net/article/117204.htm)
(在併發場景中)
拋出異常: 當前線程沒法執行則拋異常
特殊值: 當前線程沒法執行返回null或false
阻塞: 沒法操做時阻塞線程,直到操做完畢
超時: 在設定的時間內阻塞線程, 超時後放棄操做
==============================
gc 算法
判斷gc:
引用計數 : 引用一次計數器加一
GC Roots Tracing : 根節點往下所搜,沒連接的節點就gc
gc算法:
標記-清理 : 標記被回收的,而後清理, 會產生不少內存碎片
標記-整理 : 相似標記-清理, 清理完成經過整理減小碎片
複製 : 開闊相同的內存空間, 把未回收的複製到新的內存中
新生代基本採用複製算法,老年代採用標記整理算法。cms採用標記清理
使用不一樣的GC算法:
+UseSerialGC
+UseParallelGC
+UseParNewGC
+UseConcMarkSweepGC
+UseG1
CMS concurrent mark and sweep:
1,初始標記
2,併發標記
3,從新標記
4,併發清理
查看java的工具:
jps jstat visualvm 默認的垃圾收集算法是:CMS (Linux中經過 netstat | grep java 也行吧)
雙親委派模型: 類加載的請求都會首先被傳遞到父類類加載器中, 每一個加載器的加載的文件路徑不一樣, ----》 目的爲了保證jvm的安全性
BootstrapClassLoader c實現的類加載器
ExtensionClassLoader java路徑下的ext/lib下的文件
SystemClassLoader 指定的classpath的文件
(各自加載的文件路徑不一樣)
自定義: loadclass findclass 類放在特殊的目錄下,父類加載不到時,就使用本身的加載器加載
jvm中的
Eden區 新生代 新建立的對象存放的位置 觸發minor gc
老年代 經歷過屢次gc以後, 新生代中的對象被放入老年代中 觸發 full gc / major gc
========================================================================
面試中的那點事:
前端 : jsp(jstl標籤, 內置對象) js(選擇器)
javase : hashmap hashtable等
javaee : 框架 spring springmvc hibernate和mybatis
數據庫 : select語句 mysql的存儲引擎(innodb和myisam)
linux : 基本的命令 vim
併發 : 鎖(重入鎖和synchronized) 原子類(CAS) FutureTask(AQS(CAS和一個隊列)) ConcurrentHashMap(原理)
jvm : 結構 (堆,棧, 寄存器, 方法區) 類加載器(雙親委派模型)
gc : 收集算法 判斷回收的方式 回收的地方
---------------------------星期天---------------------------------
ReadWriteLock (ReadLock / WriteLock)
-> ReentrantReadWriteLock (同一線程對鎖的重複獲取)
寫鎖的降級 / 讀鎖的升級
公平鎖 / 非公平鎖(synchronized使用非公平) (公平鎖維護隊列,效率低)
自旋鎖 (在 while 循環中一直判斷某個條件,直到經過條件時才進入下個臨界)
===============================
volatile 不加時怎麼通知另外一個線程讀取刷新的數據
兩個線程 (這個問題應該是從 jmm 的方面去回答)
問題解決 --> https://segmentfault.com/a/1190000009828216
JMM模型
==============================
jvm 的各個區域的做用 (http://www.jianshu.com/p/54eb60cfa7bd)
共享:
方法區 :被加載的類信息、常量、靜態變量
堆 :存放對象實例、數組
線程私有:
虛擬機棧 :基本數據類型的數據,以及對象的引用
本地方法棧 :(native方法)
線程計數器 :執行字節碼指示器,指示下一個執行的指令
StackOverflow 和 OutofMemory 的區別
若是線程須要的空間大於容許值,則爲StackOverflowError;若是stack空間能夠動態增長,但最後內存仍是不夠,則爲OutOfMemoryError。
每個JVM線程維護本身的JVM stack. JVM stack裏面存放 JVM棧幀. 棧幀中存放 數據和中間結果(本地變量數組, 操做符棧, 和對runtime 常量池的引用). 這些數據都比較小(對象都在堆中, 棧幀僅存放對象引用), 因此想單純經過 在棧幀中存放大數據的方法 去引入StackOverflowError, 基本是不現實的.通常都是由於方法調用嵌套層數過大.
(不斷建立對象(位於堆中) -> OutofMemory )
==============================
gc 算法
判斷gc:
引用計數 : 引用一次計數器加一
GC Roots Tracing : 根節點往下所搜,沒連接的節點就gc
gc算法:
標記-清理
標記-整理
複製
---------------------------星期一---------------------------------
https://juejin.im/entry/58b7a7e78d6d8100652747fd
------------------------------------------
innnodb 和 myisam:
1,InnoDB不支持FULLTEXT類型的索引
2,InnoDB 中不保存表的具體行數(掃描表),當count(*)語句包含 where條件時,兩種表的操做是同樣的
3,對於AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,可是在MyISAM表中,能夠和其餘字段一塊兒創建聯合索引
4,DELETE FROM table時,InnoDB不會從新創建表,而是一行一行的刪除
5,LOAD TABLE FROM MASTER操做對InnoDB是不起做用的,解決方法是首先把InnoDB表改爲MyISAM表,導入數據後再改爲InnoDB表,可是對於使用的額外的InnoDB特性(例如外鍵)的表不適用
6,InnoDB表的行鎖也不是絕對的,假如在執行一個SQL語句時MySQL不能肯定要掃描的範圍,InnoDB表一樣會鎖全表
7,MyISAM的索引和數據是分開的,而且索引是有壓縮的,內存使用率就對應提升了很多
=====》 Innodb 支持事務處理與外鍵和行級鎖
---------------------------------------------
進程間的通訊方式:
1,管道: 半雙工(數據只能單向流動),只能在具備親緣關係的進程間使用,進程的親緣關係一般是指父子進程關係
2,有名管道:半雙工,無親緣關係進程間的通訊。
3,信號量:防止某進程正在訪問共享資源時,其餘進程也訪問該資源
4,消息隊列:消息的鏈表,存放在內核中並由消息隊列標識符標識
5,信號:通知接收進程某個事件已經發生。
6,共享內存:被其餘進程所訪問的內存
7,套接字:不一樣機器間的進程通訊
---------------------------------------------
CopyOnWriteArrayList :
寫時加鎖,當添加一個元素的時候,將原來的容器進行copy,複製出一個新的容器,而後在新的容器裏面寫,寫完以後再將原容器的引用指向新的容器,而讀的時候是讀舊容器的數據,因此能夠進行併發的讀,但這是一種弱一致性的策略。
使用場景:CopyOnWriteArrayList適合使用在讀操做遠遠大於寫操做的場景裏,好比緩存。
----------------------------------------------
線程池:
1. 若是當前池大小 poolSize 小於 corePoolSize ,則建立新線程執行任務。
2. 若是當前池大小 poolSize 大於 corePoolSize ,且等待隊列未滿,則進入等待隊列
3. 若是當前池大小 poolSize 大於 corePoolSize 且小於 maximumPoolSize ,且等待隊列已滿,則建立新線程執行任務。
4. 若是當前池大小 poolSize 大於 corePoolSize 且大於 maximumPoolSize ,且等待隊列已滿,則調用拒絕策略來處理該任務。
5. 線程池裏的每一個線程執行完任務後不會馬上退出,而是會去檢查下等待隊列裏是否還有線程任務須要執行,若是在 keepAliveTime 裏等不到新的任務了,那麼線程就會退出
====》 poolSize -》 corePoolSize -》 隊列 -》maximumPoolSize -》 拒絕策略
----------------------------------------------
happens-before:
1.程序順序規則
2.監視器鎖規則
3.volatile變量規則
4.傳遞性
5.線程啓動規則
----------------------------------------------
JMM --》 直接回答 6 個模塊就好
----------------------------------------------
類加載器工做機制:
1.裝載:將Java二進制代碼導入jvm中,生成Class文件。
2.鏈接:
a)校驗:檢查載入Class文件數據的正確性
b)準備:給類的靜態變量分配存儲空間
c)解析:將符號引用轉成直接引用
3:初始化:對類的靜態變量,靜態方法和靜態代碼塊執行初始化工做。
----------------------------------------------
索引: B- , B+
----------------------------------------------
tcp的三次握手和四次揮手: (老生常談)
(1)三次握手
1,client發送標誌位SYN和隨機序列號seq給server,進入SYN_SENT
2,server接受SYN標誌獲取創建連接請求,發送SYN,ACK和ack爲接受seq+1和隨機序列號seq
server進入SYN_RCVD狀態
3,client接受確認,檢查ack是否爲seq+1,進入ESTABLISHED狀態
發送ACK=1和ack爲接受server的seq+1,server確認ack是否爲本身發送的序列號值+1,
server進入ESTABLISHED狀態
爲何三次握手:
爲了防止已失效的鏈接請求報文段忽然又傳送到了服務端,形成server等待client鏈接而浪費資源
(2)四次揮手
1, client發送FIN client進入FIN_WAIT_1狀態
2, server接受FIN 發送ack爲接受的FIN值+1,server進入CLOSE_WAIT狀態 client進入FIN_WAIT_2狀態
3, server發送FIN 關閉server到client的鏈接,server進入LAST_ACK狀態
4, client接受FIN client進入TIME_WAIT 發送ACK=1和ack爲接受server的FIN+1,server進入CLOSED狀態
爲何四次揮手:
client端發送關閉鏈接請求,不發送數據但仍是能接受數據,
此時server端等待數據所有發送完成以後再發送關閉請求關閉鏈接
----------------------------------------------
tcp和udp的區別:
1,面向鏈接和麪向無鏈接
2,tcp提供可靠傳輸,無差錯,不丟失,不重複,按順序,udp盡最大努力
3,tcp面向流, udp是數據包
4,tcp有擁塞控制,網絡擁塞時主機下降發送速率
5,tcp一對一, udp一對多,多對多,多對一,一對一
6,tcp全雙工通訊信道
7,tcp首部開銷20字節,udp8字節
----------------------------------------------
http://mp.weixin.qq.com/s?__biz=MzA3NTUzNjk1OA==&mid=2651560829&idx=1&sn=30f50202d3dc3540e4bdba19e531a47e&chksm=8490342cb3e7bd3a88e56b59f054f3b01e47c509494d811f62cfa832e69cd380663b078816c8&mpshare=1&scene=1&srcid=0917bQEVdZKntgVoqKZZgRzi#rd
輸入url以後發生的事情:
1,輸入地址
瀏覽器匹配輸入的地址,或者有些直接從緩存獲取網頁
2,瀏覽器查找域名的ip地址
(1)從hosts文件裏查找對應的域名對應ip的記錄,如有,則使用
(2)想本地DNS服務器發送一個DNS請求
(3)本地DNS服務器查找緩存中的記錄,如有則返回結果,
若沒有,遞歸向根DNS服務器查詢
(4)根DNS服務器給給本地DNS服務器相對應的域名服務器的地址,進行迭代查詢
(5)本地DNS服務器向域名服務器發送請求,獲取域名解析服務器的地址
(6)域名解析服務器返回域名和ip對應關係,本地DNS服務器返回用戶的同時
將對應關係緩存在本地DNS服務器中,以備以後查詢
DNS兩種查詢:
(1)遞歸解析
DNS服務器自身不能解析,向根域名查詢,再由根域名服務器一級一級向下查詢
(2)迭代解析
DNS服務器自身不能解析,其餘DNS服務器告訴能解析該域名的DNS服務器的ip地址,
讓DNS服務器自身再發請求去查詢
3, 瀏覽器向web服務器發送HTTP請求
TCP三次握手 四次揮手 看上面
4, 服務器的永久重定向響應
爲何重定向:
所搜引擎把同一個網站不一樣的地址定向到相同的網站去
301 :舊地址已經不存在, 新舊地址都到重定向的頁面去
302 :舊地址存在, 搜索引擎抓取新地址而保持舊的網址
5, 瀏覽器跟蹤重定向地址
瀏覽器訪問地址了
6, 服務器處理請求
創建與服務器的鏈接,等待服務器返回結果
7,服務器返回HTTP響應
8,瀏覽器顯示HTML
9,瀏覽器發送請求獲取嵌在HTML中的圖片等資源
----------------------------------------------
(https://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html)
java nio
BIO :
每次來一個請求(顧客),就分配到線程池中由一個線程處理,若是超出了線程池的最大上限,就扔到隊列等待 。
nio :
mainReactor線程負責監聽server socket,accept新鏈接,並將創建的socket分派給subReactor;subReactor能夠是一個線程,也能夠是線程池(通常能夠設置爲CPU核數),負責多路分離已鏈接的socket,讀寫網絡數據
-----------------------------------------------
編程的題目都彙總在這了:
KMP
public class KMP {
public static int kmp(String str, String dest,int[] next){//str文本串 dest 模式串
for(int i = 0, j = 0; i < str.length(); i++){
while(j > 0 && str.charAt(i) != dest.charAt(j)){
j = next[j - 1];
}
if(str.charAt(i) == dest.charAt(j)){
j++;
}
if(j == dest.length()){
return i-j+1;
}
}
return 0;
}
public static int[] kmpnext(String dest){
int[] next = new int[dest.length()];
next[0] = 0;
for(int i = 1,j = 0; i < dest.length(); i++){
while(j > 0 && dest.charAt(j) != dest.charAt(i)){
j = next[j - 1];
}
if(dest.charAt(i) == dest.charAt(j)){
j++;
}
next[i] = j;
}
return next;
}
public static void main(String[] args){
String a = "ababa";
String b = "ssdfgasdbababa";
int[] next = kmpnext(a);
int res = kmp(b, a,next);
System.out.println(res);
for(int i = 0; i < next.length; i++){
System.out.println(next[i]);
}
System.out.println(next.length);
}
}
樹的遍歷
(關於樹, 這 http://blog.csdn.net/tuke_tuke/article/details/51438751
講解了許多題目, 看一下
)
給先序後序而後構建二叉樹
快排
單例五個方式
TOPK
45度打印二維數組
快排 :
堆排序
dijkstra : http://www.cnblogs.com/junyuhuang/p/4544747.html
BFS
DFS
二叉樹的高度(也有遞歸和非遞歸之分)
重構二叉樹
最長公共子序列
---------------------------星期二---------------------------------
ArrayList擴容,HashMap擴容怎麼實現
HashMap: (java8已經變成紅黑樹了,有空看一下吧)
兩個參數 :初始容量 和 加載因子 (默認爲16,和0.7)
每次增長元素,判斷當前容量是否到達 當前容量*裝載因子的大小
超過期,發生rehash操做,容量變爲原來的2倍,原來的元素再通過hash放入新的桶數組中
(rehash操做判斷原來容量是否爲Integer.MAX_VALUE,如果,則直接把threshold設置爲Integer.MAX_VALUE)
--》能夠用 Collections的synchronizedMap方法使HashMap具備線程安全的能力,或者使用ConcurrentHashMap
ArrayList:
默認大小爲10
擴容爲原來大小的1.5倍+1
原來的數據經過 Arrays.copyOf 方法複製
------------------------------
TreeMap:
實現SortedMap接口,可以把它保存的記錄根據鍵排序,默認是按鍵值的升序排序,也能夠指定排序的比較器,
key必須實現Comparable接口或者在構造TreeMap傳入自定義的Comparator,不然會在運行時拋出java.lang.ClassCastException類型的異常
(實現原理)
------------------------------
java8 中的 HashMap: 數組+鏈表+紅黑樹 (鏈表大於8時轉化成紅黑樹 。。。 (紅黑樹的增刪改,心好累。。))
Node是HashMap的一個內部類,實現了Map.Entry接口,本質是就是一個映射(鍵值對)
採用鏈地址法, 就是數組加鏈表的結合,對鍵hash以後放在對應桶數組下標的鏈表中
獲取桶數組索引位置:
經過h & (table.length -1)來獲得該對象的保存位,而HashMap底層數組的長度老是2的n次方
h& (length-1)運算等價於對length取模,也就是h%length
jdk1.8中 hash算法: 經過hashCode()的高16位異或低16位實現的:(h = k.hashCode()) ^ (h >>> 16)
-------------------------------
線程有多少種狀態 (5種狀態)
1,
新建狀態:新建立了一個線程對象。
2,
就緒狀態:線程對象建立後,其餘線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
3,
運行狀態:就緒狀態的線程獲取了CPU,執行程序代碼。
4,
阻塞狀態:阻塞狀態是線程由於某種緣由放棄CPU使用權,暫時中止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。阻塞的狀況分三種:
(1)等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。
(2)同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。
(3)其它阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程從新轉入就緒狀態。
5,
死亡狀態:線程執行完了或者因異常退出了run()方法,該線程結束生命週期。
-------------------------------
一致性哈希 。。。什麼鬼
-------------------------------
圖的的環檢測(深搜)
有向圖(DFS)
/*
* 1,白點集合,裏面放還沒explore的點
* 2,灰點集合,裏面放正在explore的點,當前的灰點們表示一條正在explore的路徑,這個路徑上的每一個點都是灰的
* 3,黑點集合,裏面放已經explore的點且這些點不構成環
*
* 黑色節點表示該節點的全部的鄰接節點都已經被訪問過了
* 若將要訪問的點是個灰點,則表示發現了環
*/
public boolean hasCycleDirectedGraph(int n, int[][] edges) {// 前指後
HashSet<Integer> black = new HashSet<Integer>();
HashSet<Integer> white = new HashSet<Integer>();
HashSet<Integer> gray = new HashSet<Integer>();
List<List<Integer>> adjList = new ArrayList<List<Integer>>();
// 這裏是在爲每一個節點添加一個表達臨近節點的集合
for (int i = 0; i < n; ++i) {
white.add(new Integer(i));
adjList.add(new ArrayList<Integer>());
}
// 這裏是在 設置臨近節點的集合
for (int[] edge : edges) {
adjList.get(edge[0]).add(new Integer(edge[1]));
}
//
for (int i = 0; i < n; i++) {
if (white.contains(i)) {
if (hasCycle(i, white, gray, black, adjList))
return true;
}
}
return false;
}
private boolean hasCycle(Integer vertex, HashSet<Integer> white, HashSet<Integer> gray, HashSet<Integer> black,
List<List<Integer>> adjList) {
white.remove(vertex);
gray.add(vertex); // current vertex is being visited
for (Integer succ : adjList.get(vertex)) { // successors of current
// vertex
if (white.contains(succ)) {
if (hasCycle(succ, white, gray, black, adjList)) {
return true;
}
} else if (gray.contains(succ)) {
return true;
} else if (black.contains(succ)) {
continue;
}
}
gray.remove(vertex);
black.add(vertex);
return false;
}
無向圖 (並集查找 DFS)
並集查找:
/*
* 開始這個圖只有頂點,沒有邊,咱們來一條一條的添加邊。
* 每遇到一條邊,判斷這邊的兩個端點是否在同一個集合裏?
*
* 在的話,表示有環:由於兩個點在一個集合裏就表示這兩個點已經有一條路徑了,如今再加一條路徑,必然構成環。
* 不在的話,表示不構成環,咱們應該合併這兩個集合:由於加上這條邊,兩個集合就被連起來了,合併成了一個集合
*
*
*/
public static void main(String[] args) {
int[][] edges = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 1, 3 }, { 1, 4 } };
int n = 5;
UnDirectCircle directCircle = new UnDirectCircle();
System.out.println(directCircle.validTree(n, edges));
}
public boolean validTree(int n, int[][] edges) {
UnionFind uf = new UnionFind(n);
for (int[] edge : edges) {
int p = edge[0];
int q = edge[1];
if (uf.find(p) == uf.find(q))
return false;
else
uf.union(p, q);
}
return uf.count() == 1;
}
}
class UnionFind {
private int[] father;
private int count;
public UnionFind(int n) {
father = new int[n];
count = n;
// 初始化全部節點的父節點爲節點自己
for (int i = 0; i < n; i++) {
father[i] = i;
}
}
public int count() {
return this.count;
}
public int find(int p) {
int root = father[p];
// 找到節點的最高的父節點
while (root != father[root])
root = father[root];
// as long as we get here, root is the final dad
// p 當前節點 father[p] 當前節點的父節點 迭代更新當前路徑上的全部的節點爲最高父節點
while (p != root) {
int tmp = father[p];
father[p] = root;
p = tmp;
}
return root;
}
public void union(int p, int q) {
int fatherP = find(p);
int fatherQ = find(q);
if (fatherP != fatherQ) {
father[fatherP] = fatherQ;
count--;
}
}
}
DFS:
public boolean validTree(int n, int[][] edges) {
HashSet<Integer> visited = new HashSet<Integer>();
List<List<Integer>> adjList = new ArrayList<List<Integer>>();
for (int i = 0; i < n; ++i)
adjList.add(new ArrayList<Integer>());
for (int[] edge : edges) {
adjList.get(edge[0]).add(edge[1]);
adjList.get(edge[1]).add(edge[0]);
}
if (hasCycle(-1, 0, visited, adjList)) // has cycle?
return false;
if (visited.size() != n) // is all connected?
return false;
return true;
}
private boolean hasCycle(Integer pred, Integer vertex, HashSet<Integer> visited, List<List<Integer>> adjList) {
visited.add(vertex); // current vertex is being visited
for (Integer succ : adjList.get(vertex)) { // successors of current
// vertex
if (!succ.equals(pred)) { // exclude current vertex's predecessor
if (visited.contains(succ)) {
return true; // back edge/loop detected!
} else {
if (hasCycle(vertex, succ, visited, adjList)) {
return true;
}
}
}
}
return false;
}
-------------------------------
缺頁操做系統如何處理
每當所要訪問的頁面不在內存時,會產生一次缺頁中斷,
此時操做系統會根據頁表中的外存地址在外存中找到所缺的一頁,
將其調入內存。
1. 保護CPU現場
2. 分析中斷緣由
3. 轉入缺頁中斷處理程序進行處理
4. 恢復CPU現場,繼續執行
在FIFO算法中,先進入內存的頁面被先換出
在LRU算法中,最近最少使用的頁面被先換出
在OPT算法中,在最遠的未來才被訪問的頁面被先換出
-------------------------------
簡單講講操做系統內存管理機制,
段式與頁式內存管理的優缺點(順道講了下段頁式)
-------------------------------
RPC (grpc dubbo thrift)
RPC 工做流程:
(1) client以本地調用方式調用服務
(2) client sub序列化調用請求的方法,參數,併發送到服務端
(3) server stub反序列化請求的方法和參數,並調用本地的服務
(4) server stub序列化返回值,併發送回client stub
(5) client stub反序列化收到的返回結果,並返回給調用的服務
原理 -》 JDK的動態代理 字節碼 CGLIB
requestId ---》 解決多個請求狀況下 response 對應 request
(1) 線程調用rpc時生成惟一requestId,而且和處理結果的回調對象callback
一塊兒放入到ConcurrentHashMap中
(2) callback的get方法未獲取結果則調用wait方法讓當前線程等待
(3) server端返回結果時,根據requestId在ConcurrentHashMap中獲取處理結果的Callback對象
調用callback的notifyAll喚醒線程
ps : RMI 只支持java應用(返回java對象和基本類型) rpc支持多語言
-------------------------------
(https的問題 : http://www.jianshu.com/p/072a657337ae)
HTTPS如何實現
1, 瀏覽器將本身支持的一套加密規則發送給網站
2, 網站從中選出一組加密算法與HASH算法,併發送證書信息(包含公鑰)
3, 瀏覽器驗證證書的合法性,若信任,生成隨機密碼,並用公鑰加密隨機密碼,
用約定的HASH算法計算握手消息,並用隨機密碼對其加密,返回給網站
4, 網站用私鑰解密瀏覽器的隨機密碼,再用密碼解密握手消息,(?這裏不懂?)並驗證HASH是否一致
網站使用密碼加密一段握手消息,發給瀏覽器
5, 瀏覽器解密並計算握手消息的HASH,驗證與服務端發送的HASH是否一致,握手結束
通訊數據將由以前瀏覽器生成的隨機密碼並利用對稱加密算法進行加密
非對稱加密算法用於在握手過程當中加密生成的密碼,
對稱加密算法用於對真正傳輸的數據進行加密,
而HASH算法用於驗證數據的完整性
Point:(客戶端產生的對稱密鑰(隨機密碼)用非對稱加密算法傳輸, 以後傳輸的消息使用對稱密鑰進行加密)
1,服務器下發的內容不可能被僞造,由於別人都沒有私鑰,因此沒法加密。
強行加密的後果是客戶端用公鑰沒法解開。
2,任何人用公鑰加密的內容都是絕對安全的,由於私鑰只有服務器有,
也就是隻有真正的服務器能夠看到被加密的原文。
-------------------------------
對稱加密與非對稱加密
對稱加密 : 對原始數據的可逆變換 好比對一列數每位數字加一
非對稱加密 :有兩個祕鑰,一個是公鑰,一個是私鑰。公鑰加密的內容只有私鑰能夠解密,私鑰加密的內容只有公鑰能夠解密
--------------------------------
信息安全傳輸
1,客戶端和服務器直接的通訊只有本身能看懂
2,客戶端和服務器能夠校驗數據是否被修改過
3,第三方沒法冒充服務器
--------------------------------
通訊網絡協議棧
物理層: 實現比特流的透明傳輸 CSMA/CD
數據傳輸層: 流數據封裝成幀 ARP/RAPR
MAC子層的主要任務是,完成網絡介質的訪問控制;
LLC子層的主要任務是創建和維護網絡鏈接,執行差錯校驗、流量控制和鏈路控制。
網絡層: 分組傳輸 路由選擇 ICMP
傳輸層:通訊子網和資源子網的接口和橋樑 提供可靠的端到端的差錯和流量控制,保證報文的正確傳輸 TCP/IP UDP
會話層:向兩個實體的表示層提供創建和使用鏈接的方法 RPC
表示層:處理用戶信息的表示問題,如編碼、數據格式轉換和加密解密
應用層: 應用程序 HTTP FTP SMTP TELNET
--------------------------------
TCP擁塞控制,流量控制,
http://blog.csdn.net/yechaodechuntian/article/details/25429143
--------------------------------
滑動窗口協議,糊塗窗口
--------------------------------
http://java.jr-jr.com/2015/12/10/io-nio/
select和epoll : http://www.cnblogs.com/Anker/p/3265058.html
問題 :
Epoll與Select區別以及epoll優勢,
爲何通常狀況下epoll性能比select好,ET模式與LT模式
select工做過程: (fd : 文件描述符)
1,調用select函數,將fd_set從用戶空間拷貝到內核空間
2,註冊回調函數
3,遍歷fd,調用對應的poll方法(對於socket,有tcp_poll,udp_poll或者datagram_poll)
4,回調函數把當前進程掛到設備的等待隊列中,
當設備收到一條消息(網絡設備)或填寫完文件數據後(磁盤設備),
會喚醒設備等待隊列上睡眠的進程,這時current便被喚醒了。
5,poll方法返回讀寫操做是否就緒的狀態碼,並賦給fd
6,若遍歷全部fd而沒有可讀寫的狀態碼,調用select的進程調用schedule_timeout休眠一段時間,
等待設備資源可讀寫後喚醒,從新遍歷fd,如此循環
7,把全部fd_set從內核空間拷貝到用戶空間
缺點:
(1)每次調用select,都須要把fd集合從用戶態拷貝到內核態,這個開銷在fd不少時會很大
(2)同時每次調用select都須要在內核遍歷傳遞進來的全部fd,這個開銷在fd不少時也很大
(3)select支持的文件描述符數量過小了,默認是1024
select/poll每次調用都會線性掃描所有的集合,致使效率呈現線性降低
epoll epoll_create,epoll_ctl和epoll_wait,
epoll_create是建立一個epoll句柄;
epoll_ctl是註冊要監聽的事件類型;
epoll_wait則是等待事件的產生
epoll_create 每次註冊新的事件到epoll句柄中時 把全部的fd拷貝進內核,保證了每一個fd在整個過程當中只會拷貝一次
epoll_ctl時把當前進程掛一遍,併爲每一個fd指定一個回調函數,當設備就緒,喚醒等待隊列上的等待者時,就會調用這個回調函數,而這個回調函數會把就緒的fd加入一個就緒鏈表
epoll_wait的工做實際上就是在這個就緒鏈表中查看有沒有就緒的fd
epoll沒有這個限制,它所支持的FD上限是最大能夠打開文件的數目
總結:
1,select,poll實現須要本身不斷輪詢全部fd集合,直到設備就緒,
epoll只須要在喚醒時判斷一下就緒鏈表是否爲空就好了,這節省了大量的CPU時間
2,select,poll每次調用都要把fd集合從用戶態往內核態拷貝一次
epoll只要一次拷貝,並且把current往等待隊列(epoll內部定義的,不是設備等待隊列)上掛也只掛一次
epoll 的 LT 和 EL :
1,LT (level triggered)是缺省的工做方式,而且同時支持block和no-block socket.
內核告訴你一個文件描述符是否就緒了,而後你能夠對這個就緒的fd進行IO操做
若是你不做任何操做,內核仍是會繼續通知你的
2,EL (edge-triggered)是高速工做方式,只支持no-block socket
當描述符從未就緒變爲就緒時,內核經過epoll進行一次通知,以後再也不通知
--------------------------------
TCP 和 UDP 的區別
??發送3個80字節包,TCP與UDP下對端分別接受幾回(其實就是TCP與UDP區別之一,TCP基於流)
都屬於 OSI 中的傳輸層的協議
TCP 面向鏈接, UDP 無鏈接
TCP首部開銷20字節,UDP首部開銷8字節
TCP邏輯通訊信道是全雙工的可靠信道,UDP則是不可靠信道
UDP沒有擁塞機制,所以網絡出現擁堵不會使源主機的發送效率下降
TCP的鏈接只能是點到點的,UDP支持一對一,多對一,多對多的交互通訊
TCP 應用:Telnet(遠程登陸)、FTP(文件傳輸協議)、SMTP(簡單郵件傳輸協議)。
TCP用於傳輸數據量大,可靠性要求高的應用
UDP 應用:NFS(網絡文件系統)、SNMP(簡單網絡管理系統)、DNS(主域名稱系統)、
--------------------------------
IPC有哪些,共享內存原理
-------------------------------
什麼是緩存,爲何須要緩存,有哪些緩存使用場景
緩存是臨時存放數據(使用頻繁的數據)的地方,介於外部請求和真實數據之間。
1,硬件緩存 硬盤(CPU)與外界接口(一般是內存)之間的暫存器
2,客戶端緩存
3,服務端緩存 數據庫鏈接
--------------------------------
https://yikun.github.io/2015/04/03/%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AALRU-Cache%EF%BC%9F/
LRU cache思路
(1) 基於HashMap和雙向鏈表的實現
獲取時從HashMap中獲取Node,並更新到當前鏈表的頭部
插入時,從HashMap獲取Node,更新節點到鏈表頭部並修改節點的值爲新值
(2) 使用 LinkedHashMap 在構造函數傳入 緩存容量,裝載因子, 訪問規則爲true
(access-order爲true時會更新訪問的值到隊列頭部), 重寫 removeEldestEntry方法
ps:關於LinkedHashMap的構造函數的第三個參數:
tt>true</tt> for access-order, <tt>false</tt> for insertion-order
private int capacity;
private Map<Integer, Integer> cache;
public LRUCache(int capacity) {
this.capacity = capacity;
this.cache = new java.util.LinkedHashMap<Integer, Integer> (capacity, 0.75f, true) {
// 定義put後的移除規則,大於容量就刪除eldest
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > capacity;
}
};
}
--------------------------------
操做系統調度算法
1,先來先服務調度算法(FCFS)
維護任務隊列,先進隊列的做業或進程先分配資源並建立進程投入運行,
直到完成或阻塞
2,短做業(進程)優先調度算法(SJF)
從隊列中獲取一個估計執行時間最短的任務,分配資源並執行
3,優先權調度算法
從任務隊列中獲取優先級最高的任務並執行
(1)非搶佔式
選取一個最高優先級的任務後,不能再爲另外一個優先級的任務分配資源
(2)搶佔式
選取一個當前最高優先級的任務後,如有另外一個更高優先級的任務進入隊列,則從新進行分配
4,高響應比優先調度算法
短做業優先算法 結合 優先權算法
讓隊列中的長任務在等待過程當中不斷提升自身的優先級,
保證了長任務因爲短任務的執行而沒有分配資源的狀況
5,時間片輪轉法
爲任務隊列中的做業或進程程分配一個時間段,該時間段內
執行該任務,超時發送中斷請求暫停執行
6,多級反饋隊列調度算法
設置多個隊列,爲每一個隊列分配不一樣的時間片和不一樣的優先級,
而後循環執行隊列的任務
(最好的算法:沒必要事先知道各類進程所需的執行時間,並且還能夠知足各類類型進程的須要)
--------------星期天------------------
Nginx 負載均衡算法:
輪詢
找最少的鏈接數
響應最快鏈接最少的
IP_HASH算法
--------------------------------
回話一致性:
(1) cookie insertion
服務器返回響應後,nginx向客戶端植入cookie,客戶端帶着cookie,Nginx根據cookie轉發請求
(2) stiky session
服務器第一次響應後,產生route信息, nginx經過訪問route_cookie, route_session 中第一個不爲空的
做爲route
(3) learn
從已有的session中選擇服務器
--------------------------------
InputStream 和 Reader 的區別
(1) InputStream是表示字節輸入流的全部類的超類 讀出來的 byte 數組
(2) Reader是用於讀取字符流的抽象類 讀出來的 char 或 String
區別
1,InputStreamReader , FileReader 涉及到編碼問題, FileInputStream 不會1,
2,BufferReader類用來包裝全部其 read() 操做可能開銷很高的 Reader(如 FileReader 和InputStreamReader)
例如:
1) File file = new File ("hello.txt");
FileInputStream in=new FileInputStream (file);
InputStreamReader inReader=new InputStreamReader (in,"UTF-8");
BufferedReader bufReader=new BufferedReader(inReader);
2) File file = new File ("hello.txt");
FileReader fileReader=new FileReader(file);
BufferedReader bufReader=new BufferedReader(fileReader);
--------------------------------
IO和NIO的區別和原理
(1) IO是面向流的,NIO是面向緩衝區的
java io 從流中讀取字節,直到讀完全部的字節,中間並無緩存的過程;
java nio 先把數據讀取到緩存中,在緩存中對數據進行移動操做,增長處理過程的靈活性
(2) 阻塞與非阻塞IO
當一個線程調用read() 或 write()時,該線程被阻塞,直到有一些數據被讀取,或數據徹底寫入。
Java NIO的非阻塞模式,使一個線程從某通道發送請求讀取數據,可是它僅能獲得目前可用的數據,若是目前沒有數據可用時,就什麼都不會獲取。直至數據變的能夠讀取以前,該線程能夠繼續作其餘的事情
非阻塞寫也是如此。一個線程請求寫入一些數據到某通道,但不須要等待它徹底寫入,這個線程同時能夠去作別的事情。 線程一般將非阻塞IO的空閒時間用於在其它通道上執行IO操做,因此一個單獨的線程如今能夠管理多個輸入和輸出通道
(3)
使用單線程Selector來管理多個通道,減小系統開銷
--------------------------------
NIO中select的實現機制
(1) 建立Selector
(2) 向Selector註冊通道
(3) SelectionKey
(4) 經過Selector選擇通道
(5) wakeup
(6) close()
--------------------------------
synchronized 和 lock 的分區別:
(1) 二者都有相同的併發性和內存語義
synchronized 沒有超時等待的機制
lock 有超時機制
(2) ReentrantLock 獲取鎖定三種方式
1, lock(), 若是獲取了鎖當即返回,若是別的線程持有鎖,當前線程則一直處於休眠狀態,直到獲取鎖
2, tryLock(), 若是獲取了鎖當即返回true,若是別的線程正持有鎖,當即返回false;
3, tryLock(long timeout,TimeUnit unit), 若是獲取了鎖定當即返回true,若是別的線程正持有鎖,會等待參數給定的時間,在等待的過程當中,若是獲取了鎖定,就返回true,若是等待超時,返回false;
4, lockInterruptibly:若是獲取了鎖定當即返回,若是沒有獲取鎖定,當前線程處於休眠狀態,直到或者鎖定,或者當前線程被別的線程中斷
(3) synchronized jvm層面上,能夠監控,異常時自動釋放鎖
lock 必定要在 finally中調用unlock方法
--------------------------------
TCP/IP 協議棧
可分爲三個層次:網絡層、傳輸層和應用層。
在網絡層有IP協議、ICMP協議、ARP協議、RARP協議和BOOTP協議。
在傳輸層中有TCP協議與UDP協議。
在應用層有:TCP包括FTP、HTTP、TELNET、SMTP等協議
---------------------------------
Http 長鏈接和短鏈接的區別
短鏈接: ( ----》服務器的鏈接 )
鏈接->傳輸數據->關閉鏈接
短鏈接是指SOCKET鏈接後發送後接收完數據後立刻斷開鏈接
長鏈接: (操做頻繁時, TCP的三次握手下降效率 --》 數據庫的鏈接 )
鏈接->傳輸數據->保持鏈接 -> 傳輸數據-> 。。。 ->關閉鏈接。
長鏈接指創建SOCKET鏈接後無論是否使用都保持鏈接 (Connection:keep-alive)
--------------------------------
web app 是如何初始化spring和struts容器的
--------------------------------
servletlistener與fliter你知道多少
--------------------------------
生產者和消費者模式
--------------------------------
jsp 內置對象
request 客戶端的請求
response 服務端返回結果
session 服務端建立的與用戶請求相關的對象
application 對象中的內容直到應用關閉纔會消失
page 當前jsp頁面
pageContext 獲取其餘範圍的參數信息(request, response等)
out 在瀏覽器中輸出信息
exception 異常信息
config 獲取服務器的配置信息, 在web.xml中提供jsp的相關參數
--------------------------------
星期天刷的yy的面經:
http://blog.csdn.net/brushli/article/details/50494037
--------------------------------
線程池的使用 :
先回答從 corePoolSize 等待隊列 maximunPoolSize 拒絕策略
等待隊列:
1, ArrayBlockingQueue 基於數組的有界阻塞隊列 FIFO
2, LinkedBlockingQueue 基於鏈表的阻塞隊列 FIFO
3, SynchronousQueue 不存儲元素的隊列, 插入操做都要等另外一個現成調用移除操做,不然插入一直處於阻塞狀態
CachedThreadPool使用該隊列
4, PriorityQueue 具備優先級的阻塞隊列
拒絕策略 :
1, AbortPolicy 直接拋異常
2,CallerRunsPolicy 調用者本身運行該任務
3,DiscardOldestPolicy 丟棄最近的一個任務,並運行當前線程
4,DiscardPolicy 丟棄任務不處理
線程池執行任務:
execute 向線程池提交不須要返回值的任務
submit 提交有返回值的任務
線程池的關閉 :
shutdownNow
: 線程池置爲STOP狀態,中止全部正在執行的任務或暫停任務的列表,返回等待執行的任務列表
shutdown
: 線程池置爲SHUTDOWN狀態, 而後中斷全部當前不在執行狀態的線程
Executor框架 :
FixedThreadPool : 固定線程數的線程池
SingleThreadExecutor : 使用單個線程的executor
場景:保證順序執行任務
CachedThreadPool : 根據須要建立新的線程
------------------------------------
工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式
適配器模式、裝飾者模式、代理模式、外觀模式、橋接模式、組合模式、享元模式
策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、
備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式
併發型模式和線程池模式
struts中的 ExecutionChain 的責任鏈模式 OgnlValueStack中的裝飾模式 (封裝了一個ArrayList的對象)
hibernate的 SessionFacotory 的工廠模式
JDBC的 橋接模式
Spring bean 的單利模式
------------------------------------
如何才能產生死鎖
產生死鎖的四個必要條件:
一.互斥條件:所謂互斥就是進程在某一時間內獨佔資源。
二.請求與保持條件:一個進程因請求資源而阻塞時,對已得到的資源保持不放。
三.不剝奪條件:進程已得到資源,在末使用完以前,不能強行剝奪。
四.循環等待條件:若干進程之間造成一種頭尾相接的循環等待資源關係。
------------------------------------
產生死鎖的緣由:
一.由於系統資源不足。
二.進程運行推動的順序不合適。
三.資源分配不當。
------------------------------------
死鎖的預防
打破產生死鎖的四個必要條件中的一個或幾個,保證系統不會進入死鎖狀態。
一.打破互斥條件。即容許進程同時訪問某些資源。可是,有的資源是不容許被同時訪問的,像打印機等等,這是由資源自己的屬性所決定的。因此,這種辦法並沒有實用價值。
二.打破不可搶佔條件。即容許進程強行從佔有者那裏奪取某些資源。就是說,當一個進程已佔有了某些資源,它又申請新的資源,但不能當即被知足時,它必須釋放所佔有的所有資源,之後再從新申請。它所釋放的資源能夠分配給其它進程。這就至關於該進程佔有的資源被隱蔽地強佔了。這種預防死鎖的方法實現起來困難,會下降系統性能。
三.打破佔有且申請條件。能夠實行資源預先分配策略。即進程在運行前一次性地向系統申請它所須要的所有資源。若是某個進程所需的所有資源得不到知足,則不分配任何資源,此進程暫不運行。只有當系統可以知足當前進程的所有資源需求時,才一次性地將所申請的資源所有分配給該進程。因爲運行的進程已佔有了它所需的所有資源,因此不會發生佔有資源又申請資源的現象,所以不會發生死鎖。
四.打破循環等待條件,實行資源有序分配策略。採用這種策略,即把資源事先分類編號,按號分配,使進程在申請,佔用資源時不會造成環路。全部進程對資源的請求必須嚴格按資源序號遞增的順序提出。進程佔用了小號資源,才能申請大號資源,就不會產生環路,從而預防了死鎖。
------------------------------------
mysql數據庫的各類騷操做:
備份mysql數據
mysqldump -u root -p goods t_admin > D:backup.sql
還原mysql數據
mysql -u root -p < D:backup.sql
查看mysql幫助
mysqldump --help
MySQL查詢瀏覽器(MySQL Query Browser)
MySQL管理員(MySQL Administrator) 建立備份 、建立用戶並分配權限、
MySQL遷移工具箱(MySQL Migration Tookit) 幫你把數據從別的數據庫系統遷移到MySQL裏。
MySQL工做臺(MySQL Workbench) MySQL的建模工具。
查看mysql當前的狀態:
(1)SHOW GLOBAL STATUS;
(2)SELECT * FROM information_schema.SESSION_STATUS;
(1)QPS (每秒查詢量)、TPS(每秒事物量)
(2)增刪改查的份量
(3)鏈接數、正在使用的鏈接數、最大鏈接數
(4)慢查詢
(5)流量統計
(6)Innodb、MyISAM緩衝池
------------------------------------
聚簇索引和非聚簇索引
create cluster index 建立聚簇索引
create index 建立非聚簇索引
聚簇索引 : 表數據按照索引的順序來存儲,葉子節點儲存了真實的數據行
非聚簇索引 :表數據存儲順序與索引順序無關,葉結點包含索引字段值及指向數據頁數據行的邏輯指針
彙集索引是一種稀疏索引,數據頁上一級的索引頁存儲的是頁指針,而不是行指針。
非彙集索引,則是密集索引,在數據頁的上一級索引頁,它爲每個數據行存儲一條索引記錄。
(這裏數據頁的上一級的索引頁, 能夠參考兩張圖 -》 http://www.jb51.net/article/29693.htm)
聚簇索引:
在增長操做時,根據索引找到對應的數據頁,爲新數據騰出新空間,而後插入,可能會
形成索引頁的拆分,並調整索引指針的操做
(非聚簇索引簡單地放到表的末尾位置)
在刪除操做時,會將下方數據上移填補空缺,如果最後一頁,該數據頁會被回收,
可能形成「索引合併」(數據頁只有一行數據時,被移到臨近的數據頁)
聚簇索引使用於對範圍值搜索的狀況,由於索引值的行在物理相鄰
------------------------------------
髒讀: 讀取到其餘事物未提交的額數據
不可重複讀: 同一個事物中兩次讀取到的數據不一樣
幻讀: 事物過程當中獲取到其餘事物新提交的數據
------------------------------------
java中的事物:
JDBC事物 : 數據庫操做中一段連續的數據庫操做 setAutoCommit(false)
JTA事物 : J2EE事物服務, 由UserTransaction、TransactionManager、Transaction組成
容器事物 :spring, hibernate框架中自帶的事物實現
------------------------------------
select語句的優化:
1,對索引的考慮
(1),在where和join字段上增長索引
(2),索引創建在選擇性好的字段上
(3),符合索引是否能夠用and在where字句中替代
(4),頻繁進行數據操做的表,不要創建太多的索引;
(5),刪除無用的索引,避免對執行計劃形成負面影響
2,只選擇須要的字段
3,移除join和where語句中的計算字段
mysql和oracle的區別 http://blog.csdn.net/baidu_37107022/article/details/77043959
1,併發性:
oracle支持行級鎖,併發性要好一些, mysql的innodb的行級鎖須要依賴表的索引
2,事物:
oracle支持事物,mysql的innodb也支持
3,數據持久性:
oracle把提交的sql操做作日誌備份,異常時可經過日誌進行數據恢復
4,提交方式:
oracle須要用戶手動提交
mysql默認自動提交
5,熱備份:
oracle使用工具rman進行熱備份, 備份時不影響用戶使用數據庫
mysql的myisam使用mysqlhostcopy,會給表加讀鎖,影響使用
innodb會備份表和索引可是不會備份.frm文件
6,其餘寫sql語句時的區別
(1)單引號的區別: mysql可使用雙引號包含字符串,oracle只能用單引號
(2)自增加字段: mysql使用auto_increment, oracle使用自定義的自增加序列
(3)分頁: mysql可使用limit, oracle使用rownum
------------------------------------
你對一些框架的理解:
(1)struts2:
Dispatcher (接受用戶請求)
ActionProxy (代理用戶請求和執行元素之間的關係)
ActionInvocation (核心調度器,調度Interceptor和Action返回Result)
ActionContext(提供了操做的數據環境)
Interceptor (攔截器)
Action (執行請求處理的地方) ValueStack(對ActionContext的數據進行操做)
Result (執行結果)
(2)hibernate:
Configuration
SessionFactory
Session
Trasaction
Query 或 Criteria
hibernate中的get和load
都會先從一級緩存中查找, 而後再去二級緩存中查找對應的數據
get若是沒找到對應的數據,則返回null
load是對應配置文件中設置的lazy屬性,若未找到對象,會拋出ObjectNotFoundException
(3)Spring
IOC : 使用反射
AOP : 使用動態代理 InvocationHandler 或者CGLib
(4)SpringMVC
用戶的請求到DispatcherServlet, 分配到一個Controller, 返回一個ModelAndView,通過InternalResourceViewResolver, 返回到一個jsp頁面