JAVA知識梳理

多線程相關(guān)


死鎖

死鎖四個條件:

  1. 互斥條件

    • 臨界資源只能被一個線程擁有
  2. 占有且等待

    • 線程/進程擁有補發(fā)臨界資源,但同時請求另外一些臨界資源
  3. 占有不釋放

    • 在請求到其它臨界資源前,已擁有的臨界資源不會被釋放
  4. 循環(huán)鏈

    • 多個線程/進程形成循環(huán)請求鏈

饑餓

線程一直不能獲得所需要的資源,如:低優(yōu)先級線程請求資源一直被高優(yōu)先級線程持有

多線程操作特性

  1. 原子性

    • 操作不可中斷
  2. 有序性

    • 多線程操作是有序的,但可能出現(xiàn)cpu指令重排:

      • cpu采用流水線指令模式,可能出現(xiàn)后面指令提前到前面執(zhí)行
  3. 可見性

    • 線程對臨界資源的操作,其他線程能看到最新的臨界資源

    • violate

      • 保證有序性和可見性

      • 臨界資源發(fā)生變化時,強迫寫到共享內(nèi)存

線程狀態(tài)

  1. 新建

    • new
  2. 就緒

    • start:等待系統(tǒng)調(diào)度運行

    • yield:從運行切換到就緒,重新參與資源競爭

  3. 運行

    • run
  4. 阻塞

    • join

    • sleep

    • suspend

  5. 結(jié)束

    • 正常運行結(jié)束

    • stop: 不建議使用

  6. 中斷

    • 并不會中斷線程,只是設(shè)置中斷標識位

    • 通過中斷,使線程跳出阻塞狀態(tài)(sleep等)

線程并發(fā)包:java.util.concurrent

  1. synchronized

    • 重入鎖

      • 線程可重復(fù)訪問已獲得的臨界資源,無需釋放和再申請鎖
    • 配合object.wait,object.notify實現(xiàn)多線程通信

      • 使用前需獲得鎖

      • wait執(zhí)行完后自動釋放鎖

      • notify/notifyall不會釋放鎖,只是發(fā)送一個通知,當同步塊執(zhí)行完后才會釋放鎖

  2. 重入鎖:reentrantlock

    • 重入鎖

    • 可設(shè)置優(yōu)先響應(yīng)中斷,獲得鎖的過程中,可優(yōu)先響應(yīng)中斷,避免死鎖

    • 可設(shè)置超時時長:獲取的過程中,可設(shè)置等待時長

    • 可設(shè)置是否為公平鎖

      • 公平鎖:按申請的先后順序獲得鎖

      • 不公平鎖:隨機分配

    • 可與condition(notify/signal)配合使用,實現(xiàn)多線程通信,類似synchronized+object.wait+object.notify

  3. 信號量:semaphone

    • 實現(xiàn)多個線程同時訪問臨界資源
  4. 讀寫鎖:writereadlock

    • 讀不阻塞

    • 寫阻塞

  5. 計時器:countdownlatch

    • 計數(shù)為0時,線程訪問臨界資源,跳出阻塞
  6. 循環(huán)柵欄:cyclebarrier

    • 類似countdownlatch,但可重復(fù)計數(shù)
  7. locksupport

    • 可實現(xiàn)線程的暫停和回復(fù):park、unpark

    • 即使先unpark在park也無問題,不像suppend和resume,resume發(fā)生在suppend前出問題

線程并發(fā)集合

  1. concurrentmap

  2. collections集合方法

  3. copyandwritelist

  4. blockingqueue

線程池

創(chuàng)建線程池的幾個參數(shù):

  1. corepoolsize:核心線程數(shù)

  2. maxnumpoolsize:最大線程數(shù)

  3. keepalive:閑置線程(非核心線程)存活時間

  4. unit:存活時間單位

  5. workqueue:當無空閑線程處理任務(wù)時,任務(wù)放到該工作隊列等待調(diào)度

    • BlockingQueue實例,不同實例對應(yīng)了不同調(diào)度策略和拒絕策略
  6. threadfactory:線程創(chuàng)建工廠

  7. handler:任務(wù)拒絕執(zhí)行策略

CAS

  1. 比較并交換/無鎖/樂觀鎖

  2. a-b-a問題

    • 線程x讀取遍歷z的值為a,線程y讀取到z的值也為a,但此時z的值可能已經(jīng)經(jīng)過多次變化

    • 可通過版本號優(yōu)化

  3. AutoInteger等

    • 內(nèi)部采用死循環(huán)獲取臨界資源方式,效率低

鎖優(yōu)化

  1. 鎖持有時間

  2. 加鎖粒度:細化、粗化

  3. 鎖分離

JVM


參考:https://juejin.im/post/5b85ea54e51d4538dd08f601

java內(nèi)存劃分

    • 線程共享
  1. 方法區(qū)

    • 線程共享
  2. native棧

  3. java棧

  4. pc

java堆劃分

  1. 新生代minor

    • eden區(qū)

      • 對象一般分配在新生代的eden區(qū),大對象和長期存活對象分配在老年代

      • eden區(qū)對象經(jīng)過一次gc后,將移動到surrivor區(qū),surrivor區(qū)經(jīng)過n次(一般為15次)gc后,將移動到老年代

    • surrivor區(qū)

      • from區(qū)

      • to區(qū)

  2. 老年代major

  3. 永久代/元空間

java引用

  1. 強引用

  2. 軟引用

  3. 弱引用

  4. 虛引用

java如何標識對象是否存活?

  1. 引用計數(shù):循環(huán)計數(shù)問題

  2. 可達性分析:GCRoot

  3. string對象存活:字符串無string對象引用

  4. class存活:實例都釋放,且加載它的classloader被釋放

GC算法

  1. 標記清除

    • 標記內(nèi)存回收對象,再回收

    • 效率高,但存在內(nèi)存碎片問題

  2. 復(fù)制

    • 將內(nèi)存劃分為兩塊,在其中一款分配對象,gc后,存活的對象移動到另外一塊
  3. 標記整理

    • 類似復(fù)制,但沒有將內(nèi)存劃分為兩塊,只是在內(nèi)存的一端分配對象,存活的對象移動到另外一端
  4. 分代回收

    • 新生代:復(fù)制算法

      • 頻繁、快、高效
    • 老年代:標記清除、標記整理

      • 慢,低效,時間間隔久
  5. 常用gc處理器

    • 串行

    • 并發(fā)、并行:gc線程和用戶線程

設(shè)計模式


六大原則

  1. 單一原則

    • 類、接口、方法功能單一
  2. 里氏代換原則

    • 子類應(yīng)擴展父類抽象方法,但不應(yīng)該擴展父類非抽象方法
  3. 依賴倒置原則

    • 抽象不依賴細節(jié),細節(jié)應(yīng)該依賴抽象
  4. 接口隔離原則

    • 接口方法盡量少,功能劃分為多個接口
  5. 迪米特拉原則

    • 類對依賴的類了解盡可能少,減少代碼耦合
  6. 開放封閉原則

    • 擴展開放,修改封閉

集合/數(shù)據(jù)結(jié)構(gòu)


Collections

  1. set

    • 元素唯一

    • treeset

      • 紅黑樹結(jié)構(gòu)
    • hashset

      • hash算法計算元素存放地址
  2. list

    • arraylist

      • 線性存儲
    • vector

      • 線程安全
    • linkedlist

      • 可實現(xiàn)fifo、stack

      • 同時實現(xiàn)了list和queue

  3. queue

    • priorityqueue

      • 優(yōu)先隊列

map

  1. hashmap

    • 數(shù)組+鏈表實現(xiàn)

    • 多個數(shù)據(jù)的hash值相同時,通過鏈表連接

  2. hashtable

    • 線程安全
  3. treemap

    • 紅黑樹
  4. linkedhashmap

    • 基于雙向鏈表實現(xiàn)的hashmap

    • 支持插入排序和訪問排序

      • 訪問排序:每次訪問完后的元素放在鏈表頭,lru算法

其他

  1. hash指元素使用hash算法計算存儲地址

  2. link/tree,指元素是鏈表或者樹的結(jié)構(gòu)

IO


  1. 字節(jié)流

  2. 字符流

  3. randomaccessfile

  4. NIO

    • 非阻塞、內(nèi)存映射方式,面向塊

    • channel

    • buffer

      • 外部數(shù)據(jù)讀寫 與buffer交互
    • selector

      • 異步IO

序列化


  1. 原理

    • java為序列化對象采用序列號機制,當序列化一個對象時,先檢查該對象是否已經(jīng)序列化

      • 未序列化,采用流中數(shù)據(jù)構(gòu)建,并為該對象關(guān)聯(lián)一個序列號

      • 已序列化,直接根據(jù)關(guān)聯(lián)的序列號,獲得該對象引用

  2. 版本號

    • 根據(jù)類的超類、接口和域等屬性計算得到,當上述信息發(fā)生變化時,版本號會發(fā)生變化

    • 一般將版本號靜態(tài)寫死,防止序列化時版本號不一致發(fā)生異常

  3. static、transient域和方法,不能被序列化

  4. 序列化產(chǎn)生新的對象(不調(diào)用構(gòu)造函數(shù)),單例模式失效

創(chuàng)建對象的幾種方式


  1. 調(diào)用構(gòu)造函數(shù)

  2. new

  3. 反射

  4. 序列化

    • 不調(diào)用構(gòu)造函數(shù),通過二進制流構(gòu)造
  5. clone

    • 不調(diào)用構(gòu)造函數(shù)

其他


  1. classloader

    • 雙親委派模型

    • 引導(dǎo)classloader

      • 最頂層的加載類,主要加載核心類庫,%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等
    • 擴展classloader

      • 加載目錄%JRE_HOME%\lib\ext目錄下的jar包和class文件
    • 系統(tǒng)(應(yīng)用)classloader

      • 加載當前應(yīng)用classpath所有類

常用算法


  1. 深搜,DFS
Node* DFS(Node* root,int data)
{
    if(root.key == data)
        return root;

    Node*[] chids = data->childs();
    for(Node* child : childs)
    {
        if(child.key == data)
            return child;      
        
        DFS(child,data);
    }
}
  1. 廣搜
Node* BFS(Node* root,int data)
{
    if(root.key == data)
        return root;
    
    FIFO<Node*> fifo = new FIFO<Node*>();
    fifo.queue(root);
    
    return BFS_Visit(fifo,data);
}

Node* BFS_Visit(FIFO<Node*> fifo,int data)
{
    while(!fifo.isEmpty())
    {
        Node* item = fifo.dequeue();
        if(item.key == data)
            return item;
        
        for(Node* child : item.childs())
            fifo.queue(child);
    }
}
  1. 排序

int quick_sort_part(int data[], int start, int end)
{
       int i = start;
       int j = start;
       int key = end;
       while (i <= end)
       {
              if (data[i] < data[key])
              {
                     exchange(data[i], data[j]);
                     j++;
              }
              i++;
       }
       if (j != key)
       {
              exchange(data[j], data[key]);
       }
       return j;
}

//快速排序
void quick_sort(int data[], int start, int end)
{
       if (start < end)
       {
              int k = quick_sort_part(data, start, end);
              quick_sort(data, start, k - 1);
              quick_sort(data, k + 1, end);
       }
}
  • 合并排序

  • 堆排序

    • 最大堆

    • 最小堆

    • 二叉樹

    • 二叉搜索樹

    • b樹

    • 紅黑樹

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,886評論 0 11
  • 第二部分 自動內(nèi)存管理機制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運行數(shù)據(jù)區(qū)域 程序計數(shù)器:當前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,275評論 0 2
  • 一、Java多線程二 1.Java內(nèi)存模型 首先,程序計數(shù)器 (PC,Program CounterRegi...
    歐陽譽晨曦閱讀 306評論 0 1
  • 一、Java跨平臺的理解(Write Once, Run Anywhere) “一次編譯、到處運行”說的是J...
    歐陽譽晨曦閱讀 330評論 0 1
  • 一、運行時數(shù)據(jù)區(qū)域 Java虛擬機管理的內(nèi)存包括幾個運行時數(shù)據(jù)內(nèi)存:方法區(qū)、虛擬機棧、本地方法棧、堆、程序計數(shù)器,...
    luhanlin閱讀 602評論 0 0

友情鏈接更多精彩內(nèi)容