java知識點一

  • hashMap
hashMap的底層是數組+鏈表的結構, 使用鍵值對存儲數據, 初始化的容量是
16個, 當數組已用容量超過實際容量超過3/4時, 會進行擴容, 每次擴容要
是2的倍數, 當數組上的鏈表深度大於8時, 鏈表會轉化爲紅黑樹(提升查詢
效率);

具體實現:
hash算法和尋址算法: 
    put(key, value)時, 對key進行hash((h = 
    key.hashCode())^(h >>> 16)), key取hash值並右移16位, 和原hash值
    取異或(不相同取1, 相同取0), 尋址的公式(n -1)&hash(這裏指從新計算
    的hash), 之因此使用&運算(同爲1時爲1, 不然爲0), 而不是取模, 由於&
    效率更高, 上面之因此使用高16位和低16位異或, 能夠有效減小hash碰撞
    (有的hash值可能高16位不一樣, 低16位相同, 這樣若是和n-1進行&運算, 相
    當於高16位沒有參與到運算中);  
hash碰撞解決:
    主要是經過鏈表和紅黑樹的相互轉化;
擴容機制:
    擴容就會涉及到rehash, 數據量大的時候比較消耗性能
  • concurrentHashMap源碼解析
hashmap存在線程安全問題, 因此會出現concurrentHashMap來解決;
兩種狀況, 
    1. 兩個線程同時向map中put元素, 因爲鏈表指向的轉化, 致使數據丟失; 
    2. 一個線程put操做, 一個線程get操做, 可能會get到null值;

hashtable解決方式效率過低: 使用sychronized鎖住整個數組;

concurrentHashMap解決的原理: 使用CAS, compare and swap;
  1. 數組初始化保證線程安全:
private final Node<K,V>[] initTable() {
        Node<K,V>[] tab; int sc;
        while ((tab = table) == null || tab.length == 0) {
            if ((sc = sizeCtl) < 0)
                Thread.yield(); // lost initialization race; just spin
            //此處使用cas保證初識化時線程安全
            else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
                try {
                    if ((tab = table) == null || tab.length == 0) {
                        int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
                        @SuppressWarnings("unchecked")
                        Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
                        table = tab = nt;
                        sc = n - (n >>> 2);
                    }
                } finally {
                    sizeCtl = sc;
                }
                break;
            }
        }
        return tab;
    }

put方法的使用javascript

初始化數組完成, 可是沒有值時
    final V putVal(K key, V value, boolean onlyIfAbsent) {
        if (key == null || value == null) throw new NullPointerException();
        int hash = spread(key.hashCode());
        int binCount = 0;
        for (Node<K,V>[] tab = table;;) {
            Node<K,V> f; int n, i, fh;
            if (tab == null || (n = tab.length) == 0)
                tab = initTable();
            else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
                //此處使用cas
                if (casTabAt(tab, i, null,
                             new Node<K,V>(hash, key, value, null)))
                    break;                   // no lock when adding to empty bin
            }
            else if ((fh = f.hash) == MOVED)
                tab = helpTransfer(tab, f);
            else {
               ... 省略代碼
        }
        addCount(1L, binCount);
        return null;
    }
 
初始化數組完成, 而且有值時, 使用加鎖, 這個鎖其實只是加在一個鏈路上;
synchronized (f) {
               省略代碼...     
}

擴容時html

第一個線程來擴容的時候, 會將一個頭部節點修改成-1, 表示正在擴容, 每次從尾部開始分配給一個線程16個數組節點, 若是後續的線程發現map正在擴容, 則會幫助以前的線程進行rehash, 他會分配上一個線程前面的16個節點進行操做;
線程池
線程池的工做原理
  • 線程過來時, 會先判斷core線程是否已經滿了, 沒有的話, 就建立一個core線程執行任務;
  • 若是core線程已經滿了, 那麼他會將任務放入阻塞隊列中;
  • 當阻塞隊列也已經滿了之後, 他會判斷, 線程池是否還定義了非核心線程數, 若是有非核心線程數, 那麼就建立線程, 執行任務;
  • 當非核心線程數也已經滿了之後, 就會執行咱們定義的任務拒絕策略;
線程池的拒絕策略
ThreadPoolExecutor.AbortPolicy:丟棄任務並拋出RejectedExecutionException異常。
ThreadPoolExecutor.DiscardPolicy:丟棄任務,可是不拋出異常。
ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,而後從新提交被拒絕的任務
ThreadPoolExecutor.CallerRunsPolicy:由調用線程(提交任務的線程)處理該任務
線程池使用無界阻塞隊列會發生什麼?
一個場景, 當進行遠程調用發生阻塞的時候, 致使阻塞隊列中的任務
越積越多, 最後出現OOM的問題;
使用有界隊列, 當隊列和線程都滿了之後如何執行後續的任務?
能夠自定義拒絕策略, 將任務持久化到磁盤, 當隊列中的任務執行完以後, 到磁盤中獲取, 在執行;
機器宕機以後, 隊列中的任務怎麼辦?
此時能夠採用任務提交以前將他保存到數據庫, 並定義狀態(未提交),
當提交完成並操做完成以後, 修改狀態(已提交);

在程序啓動的時候, 定義一個後臺進程, 掃描數據庫, 將未提交的任
務進行提交;
java內存模型
有序性
程序的操做是按順序進行的, 這裏主要涉及到jvm和cpu的指令重排問題;
原子性
一個線程更新操做共享數據的時候, 不予許其餘線程進行更新操做;
可見性
一個線程對一個共享數據的操做, 其餘的線程可以看到, 內存層面就是, 一個線程更新完一個數據以後, 會將數據刷新進主內存, 另外一個線程讀數據的時候, 強制他從主內存中讀取;
volatile關鍵字的原理
主要的原理就是上面的可見性問題, volatile主要是將線程對數據的更新刷回主內存中, 並將其餘線程中使用這個數據的線程內存失效, 那麼當下次其餘線程讀取這個數據的時候, 從主內存讀取;
TCP/IP網絡模型
物理層
簡單來講就是無線信號, 網線和海底光纜之類的, 讓電腦之間能夠在物理上進行鏈接;
數據鏈路層
這一層是架構在物理層之上, 就是一臺電腦發送給另外一臺電腦的數據, 
可是存在問題, 一臺電腦發送的數據是一連串的信號, 另外一臺電腦並
不知道哪些是發給本身的, 以及發給本身的這些數據要如何解析, 因
此誕生了一些協議, 這裏面好比以太網, 互聯網:
1. 以太網: 一組電信號就是一個數據包, 就是一幀, 每幀分爲兩個
部分, head和data, head中是些描述性信息, 數據從哪來到哪去,  
以及數據的信息, data就是真實的數據, 這些數據包須要從一臺電腦
的網卡發出去, 由另外一臺電腦的網卡接收, 以太網規定, 每一個網卡都
要有一個惟一的標識, 就是mac地址, 並且網卡的數據包發送是以廣播
的方式發送給局域網內的全部電腦的, 接收方就是根據head裏面的消
息判斷這條消息是不是發給本身的;
網絡層
數據層解決了數據包發送和解析的問題, 可是, 不能區分網絡的分區,
就是那些電腦能夠互相聯通進行通訊, 網絡層裏面有IP協議, 定義了
電腦的ip地址, 每臺電腦的惟一標識, 而判斷電腦是否是一個子網的,
還須要一個子網掩碼, 將ip地址和子網掩碼進行二進制運算, 而後通
過這個二進制數來判斷哪些電腦是屬於一個子網的;

當兩個電腦不在一個局域網中時, 如何通訊鏈接, 這時候會用到路由
器, 路由器上能夠註冊電腦的IP地址和網卡地址;
傳輸層
上面解決了電腦和電腦之間的鏈接, 數據的傳輸和識別問題, 可是每一個電腦上有不一樣的應用程序, 而一臺電腦又只有一個網卡, 因此又引入端口號的概念, 每一個應用程序監聽不一樣的端口號, 進行消息接收, 這一層創建了TCP協議(如何創建鏈接, 如何發送和讀取消息, 就是tcp協議規定的);
應用層
拿到數據到底該怎麼辦, 怎麼解析, 就是這個層乾的事情, 具體的包括http協議, ftp協議...
瀏覽器請求一個網絡地址時的大概過程
1. 先走DNS解析器, 將地址解析成ip地址;
2. 走應用層的http協議, 這時候會根據http的協議對數據進行打包;
3. 包裝傳輸層, 根據tcp協議, 打包tcp協議的數據包, 包括那臺機器
的端口信息;
4. 包裝網絡層: 根據ip協議包裝數據包, 進行網絡傳輸;
5. 包裝數據鏈路層, 根據一臺網協議封裝數據包, 定義數據包接受者
ip和發送者ip等;
6. 經過路由, 交換機等對數據進行發送;
7. 接受者就根據各層的協議對數據進行層層解包;
TCP三次握手/四次揮手
三次握手
第一次: 客戶端給服務端發送請求,SYN=1, ACK=0, seq=x;
第二次: 服務端給客戶端響應, ack=x+1, SYN=1, ACK=1, seq=y;
第三次: 客戶端給服務端響應, ack=y+1, ACK=1, seq=x+1;

爲何是三次: 主要是爲了相互確認, 第一次的請求時客戶端要求服
務端創建鏈接, 第二次的請求是服務端給了客戶端響應, 客戶端確認
了本身能夠接收到服務端響應, 但此時服務端並不能肯定客戶端是否
要繼續鏈接或者可否接收到客戶端的響應, 因此須要第三次來作確認;
四次揮手
第一次揮手:客戶端向服務器發送一個FIN報文段,將設置seq爲100
和ack爲120,;此時,客戶端進入 FIN\_WAIT\_1狀態,這表示客戶端
沒有數據要發送服務器了,請求關閉鏈接;

第二次揮手:服務器收到了客戶端發送的FIN報文段,向客戶端回一個
ACK報文段,ack設置爲101,seq設置爲120;服務器進入了
CLOSE\_WAIT狀態,客戶端收到服務器返回的ACK報文後,進入
FIN\_WAIT\_2狀態;

第三次揮手:服務器會觀察本身是否還有數據沒有發送給客戶端,如
果有,先把數據發送給客戶端,再發送FIN報文;若是沒有,那麼服務
器直接發送FIN報文給客戶端。請求關閉鏈接,同時服務器進入
LAST\_ACK狀態;

第四次揮手:客戶端收到服務器發送的FIN報文段,向服務器發送ACK
報文段,將seq設置爲101,將ack設置爲121,而後客戶端進入
TIME\_WAIT狀態;服務器收到客戶端的ACK報文段之後,就關閉鏈接;
此時,客戶端等待2MSL後依然沒有收到回覆,則證實Server端已正常
關閉,客戶端也能夠關閉鏈接了;
http工做原理
http請求主要分爲請求頭和請求體, 請求頭中有狀態碼, 請求方式, 請求地址等信息, 請求體重主要是數據, 主要的過程是上面瀏覽器請求過程;
Mybatis如何防止sql注入
主要是經過#{}和${}的區別來作到的, #{}會將括號中的內容加上雙引號後加在sql語句中, 而${}則是將內容直接加在sql語句中, 前者會對sql語句進行預編譯, 後者不會, 所以使用#{}不會存在sql注入問題, ${}則會出現sql注入問題, 若是非要使用, 須要進行手動的參數校驗;
CSRF攻擊和XSS攻擊
CSRF攻擊
跨站點請求僞造攻擊, 主要是獲取客戶端的jsessionid, 去模擬客戶端請求服務端;
解決方法: 返回cookie的時候, 將設置屬性爲HttpOnly;

XSS攻擊
和上面比較相似, 只是xss攻擊使用的是將html+javascript腳本加載到客戶端電腦上執行, 一般是使用惡意連接或者在網站評論內容中書寫腳本;
解決方法: 返回的cookie, 設置HttpOnly屬性, 網站的由客戶決定並保存到數據庫的內容進行特殊字符處理;
分佈式流量攻擊
即服務端可以承受的併發量不高, 黑客使用多臺或者高性能服務器, 發送大量請求給服務端, 直接讓服務癱瘓;

當服務端承受併發量很高時, 也會存在一種狀況, 黑客會空氣其餘人的電腦, 對服務端發起大量攻擊;
相關文章
相關標籤/搜索