
、一個連接配接對應一個事務,多個連接配接的事務是不一樣的,先大概了解一下,往下看👇
本人是在學threadlocal的時候,網上大部分人都是說資料庫連接配接池是典型的用了threadloca的例子,然後我就又查資料庫連接配接池和threadloca的關系,但是,99%都說threadlocal是為了在并發的情況下,為了保證線程安全,建立了副本什麼的,其實這隻是threadlocal的用法之一,它還有個用法就是確定同一線程之間參數傳遞的友善(扯遠了)
回歸正題,還是拿上面的圖來說事。。。。
我隻講兩個關鍵點,明白人一看就懂:
1、兩者有根本性的差別,用處不一樣!
連接配接池是緩存并托管資料庫連接配接,主要是為了提高性能。
而ThreadLocal緩存連接配接,是為了把同一個資料庫連接配接“分享”給同一個線程的不同調用方法。(不管調用哪個方法,都是使用的同一個連接配接,友善進行“跨方法”的事務控制)
舉個栗子:
如果一個請求中涉及多個 DAO 操作,而如果這些DAO中的Connection都是獨立的話,就沒有辦法完成一個事務。但是如果DAO 中的 Connection 是從 ThreadLocal 中獲得的(意味着都是同一個對象), 那麼這些 DAO 就會被納入到同一個 Connection 之下。
2、重點要了解“連接配接池”。
連接配接池裡面有一定數量的連接配接資源,比如最大20個連接配接。
題外話:如果直接通過 Java原生API 擷取“直連”的話:
底層方法一般都是這樣寫的:
java.sql.DriverManager.getConnection(url, props);
java.sql.Driver.connect(url, props);
1
2
特點是:要傳入url、使用者名和密碼等資訊)
這種方式,肯定就沒有使用資料庫連接配接池。
使用資料庫連接配接池,通常都是得到一個所謂的javax.sql.DataSource[接口]的執行個體對象,它裡面包含了Connection,并且資料庫連接配接池工具類(比如C3P0、JNDI、DBCP等),肯定是重新定義了getConnection、closeConnection等方法,是以你每次得到的Connection,幾乎都不是建立立的連接配接(而是已經建立好并放到緩存裡面的連接配接),你調用closeConnection方法,也不是真正的關閉連接配接(一般都是起到一個辨別作用,辨別目前連接配接已經使用完畢,歸還給連接配接池,讓這個連接配接處于待配置設定狀态)
PS:是以說:使用資料庫連接配接池時,還是要顯式的調用資料庫連接配接池API提供的關閉連接配接的方法。
了解一下這句話:
不同的線程在同一個時間( 或者 同一個線程在多個地方)從連接配接池中拿到的Connection,肯定不是同一個連接配接。(反過來講:不同時間的兩個線程,一前一後,則有可能拿到同一個連接配接)
總結:
再好好了解一下上面的一段話,我再最後解釋億下。。。
首先,我們為了避免單一資料庫連接配接的建立和關閉耗費時間和性能,引入了資料庫連接配接池,提前建立好了n條連接配接放入池中,如果是單線程情況下,那這樣挺好的
那如果是多線程情況下呢?還是上面那段話,假設同一時間多個線程從資料庫連接配接池擷取連接配接,那肯定拿的是不同的連接配接,我目前線程和别的線程拿的連接配接不一樣,那我目前在crud的時候,不在一個事務之内。
假設不同時間的多個線程要從資料庫連接配接池拿連接配接,那這個時候就可能拿到的是同一個連接配接了,那我多個線程線程拿到的是同一個連接配接,也就是說在多個線程在同一個事務之内,線程a執行了插入還沒來得及送出,線程b此時來了個更新,線上程a還未操作完之前,線程b更新完了後,直接把連接配接給close了,線程a插了一半發現插不了了。。。此時肯定在想,這™是誰在搞我。
為了確定不同時間多個線程可能拿到的是同一個連接配接,那麼此時threadlocal閃亮登場,就算我拿的是“同一個連接配接”,在引入了threadlocal後,每個線程之間都會建立獨立的連接配接副本,将collection各自copy一份,這樣就互相不幹擾了。
以上是我的個人見解。
原文連結:
https://blog.csdn.net/qq_42405666/article/details/108258820版權聲明:本文為CSDN部落客「奔跑的烏龜」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。