免费A级毛片无码专区网站-成人国产精品视频一区二区-啊 日出水了 用力乖乖在线-国产黑色丝袜在线观看下-天天操美女夜夜操美女-日韩网站在线观看中文字幕-AV高清hd片XXX国产-亚洲av中文字字幕乱码综合-搬开女人下面使劲插视频

ThreadLocal的介紹與運用( 二 )


public class MyDemo {private static ThreadLocal<String> tl = new ThreadLocal<>();private String content;private String getContent() {return tl.get();}private void setContent(String content) {tl.set(content);}public static void main(String[] args) {MyDemo demo = new MyDemo();for (int i = 0; i < 5; i++) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {demo.setContent(Thread.currentThread().getName() + "的數(shù)據(jù)");System.out.println("-----------------------");System.out.println(Thread.currentThread().getName() + "--->" + demo.getContent());}});thread.setName("線程" + i);thread.start();}}}打印結(jié)果:
?

ThreadLocal的介紹與運用

文章插圖
從結(jié)果來看 , 這樣很好的解決了多線程之間數(shù)據(jù)隔離的問題 , 十分方便 。
1.3 ThreadLocal類與synchronized關(guān)鍵字1.3.1 synchronized同步方式? 這里可能有的朋友會覺得在上述例子中我們完全可以通過加鎖來實現(xiàn)這個功能 。我們首先來看一下用synchronized代碼塊實現(xiàn)的效果:
public class Demo02 {private String content;public String getContent() {return content;}public void setContent(String content) {this.content = content;}public static void main(String[] args) {Demo02 demo02 = new Demo02();for (int i = 0; i < 5; i++) {Thread t = new Thread(){@Overridepublic void run() {synchronized (Demo02.class){demo02.setContent(Thread.currentThread().getName() + "的數(shù)據(jù)");System.out.println("-------------------------------------");String content = demo02.getContent();System.out.println(Thread.currentThread().getName() + "--->" + content);}}};t.setName("線程" + i);t.start();}}}打印結(jié)果:
?
ThreadLocal的介紹與運用

文章插圖
? 從結(jié)果可以發(fā)現(xiàn), 加鎖確實可以解決這個問題 , 但是在這里我們強調(diào)的是線程數(shù)據(jù)隔離的問題 , 并不是多線程共享數(shù)據(jù)的問題, 在這個案例中使用synchronized關(guān)鍵字是不合適的 。
1.3.2 ThreadLocal與synchronized的區(qū)別? 雖然ThreadLocal模式與synchronized關(guān)鍵字都用于處理多線程并發(fā)訪問變量的問題, 不過兩者處理問題的角度和思路不同 。
synchronizedThreadLocal原理同步機制采用'以時間換空間'的方式, 只提供了一份變量,讓不同的線程排隊訪問ThreadLocal采用'以空間換時間'的方式, 為每一個線程都提供了一份變量的副本,從而實現(xiàn)同時訪問而相不干擾側(cè)重點多個線程之間訪問資源的同步性多線程中讓每個線程之間的數(shù)據(jù)相互隔離總結(jié): 在剛剛的案例中 , 雖然使用ThreadLocal和synchronized都能解決問題,但是使用ThreadLocal更為合適,因為這樣可以使程序擁有更高的并發(fā)性 。2. 運用場景_事務(wù)案例? 通過以上的介紹 , 我們已經(jīng)基本了解ThreadLocal的特點 。但是它具體的應(yīng)用是在哪里呢? 現(xiàn)在讓我們一起來看一個ThreadLocal的經(jīng)典運用場景: 事務(wù) 。
2.1 轉(zhuǎn)賬案例2.1.1 場景構(gòu)建? 這里我們先構(gòu)建一個簡單的轉(zhuǎn)賬場景: 有一個數(shù)據(jù)表account , 里面有兩個用戶Jack和Rose , 用戶Jack給用戶Rose 轉(zhuǎn)賬 。
? 案例的實現(xiàn)就簡單的用mysql數(shù)據(jù)庫 , JDBC 和 C3P0 框架實現(xiàn) 。以下是詳細(xì)代碼 :
? (1) 項目結(jié)構(gòu)
ThreadLocal的介紹與運用

文章插圖
? (2) 數(shù)據(jù)準(zhǔn)備
-- 使用數(shù)據(jù)庫use test;-- 創(chuàng)建一張賬戶表create table account( id int primary key auto_increment, name varchar(20), money double);-- 初始化數(shù)據(jù)insert into account values(null, 'Jack', 1000);insert into account values(null, 'Rose', 1000);【ThreadLocal的介紹與運用】? (3) C3P0配置文件和工具類
<c3p0-config><!-- 使用默認(rèn)的配置讀取連接池對象 --><default-config> <!--連接參數(shù) --> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property> <property name="user">root</property> <property name="password">1234</property> <!-- 連接池參數(shù) --> <property name="initialPoolSize">5</property> <property name="maxPoolSize">10</property> <property name="checkoutTimeout">3000</property></default-config></c3p0-config>

經(jīng)驗總結(jié)擴展閱讀