1. 程式人生 > 其它 >java基礎知識--02

java基礎知識--02

java基礎知識

樹越要往上長,它的根,越是要往下扎。
共勉!


synchronized
1、synchronized修飾程式碼塊
2、synchronized修飾類的普通方法
3、synchronized修飾類的靜態方法
重量級鎖鎖物件的原理(初學者的理解,可能有誤):

修飾理解:

1、synchronized修飾程式碼塊

同步語句塊的實現使用的是monitorenter 和 monitorexit 指令。


2、synchronized修飾類的普通方法

鎖的是這個物件。如物件多個普通方法被修飾,同一個物件訪問這些方法時,公用一個鎖。訪問其他沒有被synchronized修飾的普通方法,不受鎖約束。
不同物件的鎖不同,互不影響


3、synchronized修飾類的靜態方法

鎖是類鎖(.class)。這個範圍就比物件鎖大。這裡就算是不同物件,但是隻要是該類的物件,就使用的是同一把鎖。多個執行緒呼叫該類的同步的靜態方法時,都會阻塞。



四種鎖:

偏向鎖
如果一個執行緒獲得了鎖,那麼鎖就進入偏向模式。

輕量級鎖
倘若偏向鎖失敗,虛擬機器並不會立即升級為重量級鎖,它還會嘗試使用一種稱為輕量級鎖的優化手段(1.6之後加入的)。執行緒執行到安全點後,物件的Mark Word 的結構轉為輕量級鎖,原持有執行緒的的鎖資訊也跟著升級為輕量級鎖,與原執行緒競爭的外來執行緒進入自旋。

自旋鎖
輕量級鎖失敗後,虛擬機器為了避免執行緒真實地在作業系統層面掛起,還會進行一項稱為自旋鎖的優化手段。

重量級鎖
如果鎖競爭情況嚴重,某個達到最大自旋次數的執行緒,會將輕量級鎖升級為重量級鎖(依然是CAS修改鎖標誌位,但不修改持有鎖的執行緒ID)。

鎖消除
編譯時去除不可能存在共享資源競爭的鎖,如StringbBuffer自動轉為StringBuilder

參考連線0:
https://blog.csdn.net/qq_40949465/article/details/88734834

參考連線1:
https://www.cnblogs.com/xiaolovewei/p/9152718.html

自旋鎖:
https://www.jianshu.com/p/9d3660ad4358?utm_source=oschina-app

鎖是什麼: https://zhuanlan.zhihu.com/p/71156910


HTTP和HTTPS

https是在http基礎上加上安全傳輸協議,加上SSL/TLS,http常用埠80,https是443
SSL(Secure Sockets Layer、安全套接層協議)
TLS(Transport Layer Security、安全傳輸層協議),是SSL 3.0的後續版本

原理流程:
1、伺服器端存在公鑰和私鑰,瀏覽器請求伺服器,伺服器返回公鑰
2、瀏覽器生成隨機金鑰 A
3、用伺服器給的公鑰,加密(非對稱)A,傳給伺服器
4、伺服器用私鑰解密(非對稱)A
5、至此,瀏覽器、伺服器都有明文的 A,後續通訊資訊,都用A來對稱加密

參考連線:
https://blog.csdn.net/liuxingrong666/article/details/83869161



單例模式

一個類只允許有一個例項
建構函式私有化,對外暴露一個獲取物件的介面,在類中建立唯一的一個靜態例項物件。

破壞單例模式:

序列化後反系列化

反射

clone

防止破壞單例模式:
1、防止反射

定義一個全域性變數,當第二次呼叫構造方法時丟擲異常

2、防止克隆破壞

重寫clone(),直接返回單例物件

3、防止序列化破壞

新增readResolve(),返回Object物件。

當JVM從記憶體中反序列化地"組裝"一個新物件時,就會自動呼叫這個 readResolve方法來返回我們指定好的物件了, 單例規則也就得到了保證

參考連線0:
https://blog.csdn.net/fd2025/article/details/79711198

參考連線1:
https://blog.csdn.net/fd2025/article/details/79711198


泛型

概念:泛型是一個未知的資料型別

E e:Element 元素,E通常用來表示集合型別中的元素型別
T t: 是一個泛型,傳遞什麼型別,就返回什麼型別

1、 定義在類上:public class className < T > { }

在類上定義的泛型,在類的普通方法中也可以使用,但是類方法中的靜態方法不能使用,這也很好理解,靜態方法不需要例項化也能直接使用,然而還未例項化之前,誰也不知道是什麼型別,故不能在靜態方法中使用。

2、定義在方法上:public static final < T > void methodName(T t){ }
留個疑問,為什麼類中的泛型宣告是在類名字後面,而方法的泛型宣告是在返回型別前面?都放在名字後面不好嗎。。。
泛型是先定義,後使用的。放在返回型別,是為了適應這種情況:
public static final < T > T methodName(T t){ }

3、泛型類派生子類
子類明確要使用什麼型別的情況下,繼承泛型類:
public class ChildClass extends ParentClass< String > { }

子類不明確要使用什麼型別的情況下,繼承泛型類:
public class ChildClass< T > extends ParentClass< T > { }

其實也沒什麼區別,你也可以這麼寫:
public class ChildClass< Integer> extends ParentClass< Integer> { }

萬用字元 ? :
不常用萬用字元,對萬用字元感悟不深。感覺使用了萬用字元反而不靈活了。
如果要使用萬用字元,則是配合PECS原則來限制集合的讀取寫入。


PECS原則(Producer Extends Consumer Super):

PE:
如果要從集合中讀取型別T的資料,並且不能寫入,可以使用 ? extends 萬用字元;(Producer Extends)

/**
 * Created by HXH on 2021/3/18
 * @desc
 */
public class TestPECS {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();//String集合
        List<? extends Object> list1 = list;
        for (Object s : list1){
            //可以讀取,因為不管是什麼子集,都有Object型別幫它兜底,總是可以轉化成功
        }

        //不能加入,雖然Integer是Object子類
        //list1只知道型別上限是Object,卻不知具體是什麼型別,不能由父類轉子類
        //通俗一點的理解:可以看到list最先是List<String>型別,這裡是Integer型別
        list1.add(new Integer(1));//報錯
        
        list1.remove(0);//可以刪除
    }
}

CS:
如果要從集合中寫入型別T的資料,並且不需要讀取,可以使用 ? super 萬用字元;(Consumer Super)

        //能操作下限類
        List<Object> objectList = new ArrayList<>();
        List<? super String> list = objectList;
        list.add("555");//可以
        list.add(new Object());//不行

        //能操作下限類的子類
        List<Number> numberList = new ArrayList<>();
        List<? super Number> list2 = numberList;
        list2.add(2f);//可以
        list2.remove(3L);//可以
        
       //讀取
        for (Number n : list2){
            //不行
        }
        for (Object n : list2){
            //只能用Object接收
        }

參考連線0:
https://segmentfault.com/a/1190000014120746

參考連線1:
https://blog.51cto.com/flyingcat2013/1616068