疏漏總結(四)

yield和join

Thread.yield()作用是暫停當前的正在執行的線程去執行其他的線程。

yield()做的是讓當前運行線程回到可運行狀態,允許相同優先級的線程後的運行的機會。使用其的目的是使相同優先級的線程之間能夠適當的輪轉執行。但是實際情況是yield並不能保證達到讓步因爲讓步的線程還有可能被線程調度再次選中。

總的來說就是yield不會讓線程轉到等待/睡眠/阻塞狀態,很多情況下yield將線程從運行狀態轉到可運行的狀態。

join()方法作用是線程實例的join()方法可以讓一個線程在另一個線程結束後再去執行,就是使當前線程可以阻塞其他線程執行。

Thread.join()是將指定的線程加到當前線程將鏈各個交替執行的線程合併爲順序執行的線程。

跨域的流程

在這裏插入圖片描述

分佈式事務

本地事務:是用關係數據庫來控制事務,關係數據庫通常都是具有ACID特性的,傳統的單體應用通常會將數據全部存儲在一個數據庫中會藉助關係數據庫來完成事務控制。

分佈式事務:分佈式系統中一次操作由多個系統協同完成這種一次事務操作涉及多個系統通過網絡協同完成的過程稱爲分佈式事務。這裏強調的是多個系統通過網絡協同完成一個事務的過程並不是強調多個系統訪問了不同的數據庫,即使多個系統訪問的是同一個數據庫也是分佈式事務,如下圖:
在這裏插入圖片描述
另外一種分佈式事務表現是一個應用程序使用多個數據源連接不同的數據庫當一次事務需要操作多個數據源此時也是屬於分佈式事務,
在這裏插入圖片描述
第一種分佈式事務用的較多。

分佈式事務的場景:
在這裏插入圖片描述

MVCC和可重複讀

MVCC包含三個概念:隱藏列,undo log,ReadView

隱藏列:InnoDB引擎中每個數據表都有兩個隱藏列(還有一個隱藏id),分別是trx_id,創建版本號和roll-pointer(回滾指針)。其中創建版本號其實就是創建該行數據的事務id,這些隱藏列對客戶端是不可見的。

undo log:事務對數據行進行一次更新操作時,會把舊數據行記錄在一個叫做undo log的記錄中,ndo log中除了記錄數據行,還會記錄下該行數據的對應的創建版本號就是生成事務id,將原來的數據行中的回滾指針指向undo log記錄中的這行數據。在原來數據表中進行一次更新操作,如果這次更新操作回滾了,那麼就可以根據回滾指針去undo log中查找之前的數據進行復原。如果後續還有更新操作的話,就會在undo log中和之前的數據行形成一條鏈表,鏈表頭就是最新的數據,這條鏈表就叫做版本鏈。
在這裏插入圖片描述
事務的可見性是基於undo log來實現的。

ReadView:進行查詢操作時事務會生成一個ReadView,ReadView是一個事務快照準確來說是當前時間點系統內活躍的事務列表,就是說系統內所有未提交的事務都會記錄在Readview內,事務就根據它來判斷哪些數據是可見哪些是不可見的。

查詢一條數據時候事務會拿到ReadView去undo log中進行判斷,如果查到某一跳數據:

  • 先去查看undo log中的最新數據行,如果數據航的版本號小於ReadView記錄的事務id最小值,就是說明這條數據對當前數據庫是可見的可以直接作爲結果集返回;
  • 如果數據航版本號大於ReadView記錄的最大值,說明這條數據是由一個新的事務修改的對當前事務不可見,那麼順着版本鏈往下尋找第一條滿足條件的;
  • 如果數據行版本號在ReadView最小值和最大值之間,那麼就需要好進行遍歷整個ReadView,如果數據行版本號等於ReadView的某個值,說明該行數據仍然處於活躍狀態對當前事務就是不可見的。

ReadView就是這樣來判斷數據可見性的。

對讀已提交來說,事務中的每次讀操作都會生成一個新的ReadView,如果這期間某個事務提交了那麼它就會從ReadView中移除。這樣確保事務每次讀操作都能讀到相對比較新的數據。

對可重複讀來說,事務只有在第一次進行讀操作時纔會生成一個ReadView,後續的讀操作都會重複使用這個ReadView。也就是說,如果在此期間有其他事務提交了,那麼對於可重複讀來說也是不可見的,因爲對它來說事務活躍狀態在第一次進行讀操作時就已經確定下來後面不會再進行修改。

Cookie和Session

  1. cookie數據信息存放在客戶端瀏覽器上,session數據信息存放在服務器上;
  2. 單個cookie保存的數據小於等於4KB,一個站點最多保存20個cookie;對於session來說沒有上限,但是出於堆服務器端的性能考慮session內儘量不要存放過多的東西並且要設置session刪除機制;
  3. cookie中只能保存ASCII字符串,並需要通過編碼方式存儲爲Unicode字符或者二進制數據;session中能夠存儲任何類型的數據,包括且不限於string、integer、list等;
  4. cookie對客戶端是可見的是不安全的,session存儲在服務器上對客戶端是透明的不存在敏感信息泄露的危險;
  5. cookie保管在客戶端不佔用服務器資源併發大的網站是個很好的選擇;session保存在服務器端每個用戶產生一個session,併發訪問的用戶很多佔用很多的session耗費大量內存;
  6. cookie支持跨域訪問,session不支持跨域訪問;
  7. 開發通過設置cookie屬性達到使cookie長期有效的效果;session依賴JSESSIONID的cookie,而cookie JSESSIONID過期時間默認是-1,只需關閉窗口該session就會失效,因而session不能達到長期有效的效果

submit原理

  • 創建線程池的時候,可以使用executors的靜態方法,也可以使用new ThreadPoolExecutor的方式手動創建線程池,通過在線程池中指定參數達到創建不同類型的線程池的效果;
  • executors底層其實也是調用的new ThreadPoolExecutor()的方式創建的,是對不同線程池的封裝;
  • 線程的執行有兩種方式,一種是submit(runnable v)的形式,一種是execute(runnable b) 的形式,不同的是submit可以返回一個future的實現類,相同的一點是submit底層其實也是調用的execute;
  • 調用execute方法,首先判斷傳入的參數是否爲空,如果爲空拋出異常,如果不爲空使用獲取ctl值,計算出當前線程狀態碼,通過狀態碼計算出當前線程池工作線程是否小於核心線程數量;
  • 如果小於,判斷添加工作線程操作是否正常,如果正常,直接返回,如果不正常,繼續執行獲取ctl值,在添加工作線程的過程中,首先通過循環的方式保證ctl在加1的情況下狀態同步,如果不同步,一直循環到同步爲止,添加完成後,創建線程工作對象,把工作線程添加到set集合中,並執行.start,如果執行不成功,從set中刪除添加的worker對象,並且ctl回滾到之前沒有自增的值.
  • 如果上述中添加工作線程失敗,或者當前線程池中工作線程數量操作和信息數量,執行下列邏輯;
  • 判斷當前線程池是否是running狀態:
    (1)、如果不是running狀態,或者是running狀態,並且添加到線程隊列失敗,重新添加個工作線程,此時入參中第二個參數用於添加工作線程的邏輯中當前工作線程數量與最大線程數量做對比,如果添加失敗,執行reject處理類處理;
    (2)、如果是running狀態,並且添加隊列成功,重新獲取ctl值,判斷當前線程池狀態如果是不是running狀態,並且從對象中刪除成功,則當前線程交給拒絕線程處理器處理,如果不滿足上面條件,判斷當前線程池的工作線程數如果爲0,重新添加一個不帶任務的線程。

MyBatis緩存機制

MyBatis和同是持久層的hibernate一樣,都存在着緩存機制。

MyBatis緩存機制有兩級:
(1)一級緩存:
緩存存在要求:同一個SqlSession中,在沒有收到改變該數據的請求之前
緩存失效條件:不是同一個sqlsession對象,查詢過程中兩次的查詢條件不同,兩次之間進行CRUD操作,兩次之間手動清空緩存

(2)二級緩存:
作用:推擠緩存是基於同一個SqlSesion類的實例對象的。但是有些時候在web工廠中將會執行查詢操作的方法分裝在某個Service方法中,當查詢完一次後Service方法結束,此時SqlSession類的實例對象就會關閉,一級緩存就會被清空。此時若再次調用用Service方法查詢同一個信息,此時異界緩存就是空的從而無法從緩存中獲取信息!

因此可以使用二級緩存,二級緩存存在與Mapper實例中,當多個SqlSession類的實例對象加載相同的mapper文件,並執行其中國的SQL配置時,他們就共享一個Mapper緩存。當某個SqlSession類的實例對象執行增,刪,改,等改變數據的操作時,Mapper實例都會清空其二級緩存!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章