摘要:設置當前線程的局部變量副本的變量值為指定值。示例首先,我們來看看不考慮多線程共享數據的情況。使用保存對象的局部變量。各線程間同時操作自己的變量,相互間沒有影響。采用以空間換時間方式,為每一個線程都提供一份變量,各線程間同時訪問互不影響。
1. ThreadLocal版權聲明:本文由吳仙杰創作整理,轉載請注明出處:https://segmentfault.com/a/1190000009236777
ThreadLocal 不是一個線程,而是一個線程的本地化對象。當某個變量在使用 ThreadLocal 進行維護時,ThreadLocal 為使用該變量的每個線程分配了一個獨立的變量副本,每個線程可以自行操作自己對應的變量副本,而不會影響其他線程的變量副本。
2. API 方法ThreadLocal 的 API 提供了如下的 4 個方法。
1)protected T initialValue()
返回當前線程的局部變量副本的變量初始值。
2)T get()
返回當前線程的局部變量副本的變量值,如果此變量副本不存在,則通過 initialValue() 方法創建此副本并返回初始值。
3)void set(T value)
設置當前線程的局部變量副本的變量值為指定值。
4)void remove()
刪除當前線程的局部變量副本的變量值。
在實際使用中,我們一般都要重寫 initialValue() 方法,設置一個特定的初始值。
2.1 示例首先,我們來看看不考慮多線程共享數據的情況。
現在有小明、小剛、小紅三人在同一家銀行,分別向各自賬戶存入 200 元錢:
package com.wuxianjiezh.demo.threadpool; public class MainTest { public static void main(String[] args) { Bank bank = new Bank(); Thread xMThread = new Thread(() -> bank.deposit(200), "小明"); Thread xGThread = new Thread(() -> bank.deposit(200), "小剛"); Thread xHThread = new Thread(() -> bank.deposit(200), "小紅"); xMThread.start(); xGThread.start(); xHThread.start(); } } class Bank { private int money = 1000; public void deposit(int money) { String threadName = Thread.currentThread().getName(); System.out.println(threadName + "--當前賬戶余額為:" + this.money); this.money += money; System.out.println(threadName + "--存入 " + money + " 后賬戶余額為:" + this.money); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
運行結果:
小明--當前賬戶余額為:1000 小紅--當前賬戶余額為:1000 小紅--存入 200 后賬戶余額為:1400 小剛--當前賬戶余額為:1000 小剛--存入 200 后賬戶余額為:1600 小明--存入 200 后賬戶余額為:1200
結果是除了小明存錢和自己賬戶余額能對上外,小剛和小紅也都只存了 200,但他們的賬戶余額分別多了 200 和 400?
這是因為多個線程共享了同一個實例對象的局部變量所致。
使用 ThreadLocal 保存對象的局部變量。
package com.wuxianjiezh.demo.threadpool; import java.util.function.Supplier; public class MainTest { public static void main(String[] args) { Bank bank = new Bank(); Thread xMThread = new Thread(() -> bank.deposit(200), "小明"); Thread xGThread = new Thread(() -> bank.deposit(200), "小剛"); Thread xHThread = new Thread(() -> bank.deposit(200), "小紅"); xMThread.start(); xGThread.start(); xHThread.start(); } } class Bank { // 初始化賬戶余額為 100 ThreadLocalaccount = ThreadLocal.withInitial(new Supplier () { @Override public Integer get() { return 1000; } }); public void deposit(int money) { String threadName = Thread.currentThread().getName(); System.out.println(threadName + "--當前賬戶余額為:" + account.get()); account.set(account.get() + money); System.out.println(threadName + "--存入 " + money + " 后賬戶余額為:" + account.get()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
運行結果:
小明--當前賬戶余額為:1000 小紅--當前賬戶余額為:1000 小紅--存入 200 后賬戶余額為:1200 小剛--當前賬戶余額為:1000 小剛--存入 200 后賬戶余額為:1200 小明--存入 200 后賬戶余額為:1200
可以看到,我們要的效果達到了。各線程間同時操作自己的變量,相互間沒有影響。
3. ThreadLocal 與 Thread 同步機制的比較同步機制采用了以時間換空間方式,通過對象鎖保證在同一個時間,對于同一個實例對象,只有一個線程訪問。
ThreadLocal 采用以空間換時間方式,為每一個線程都提供一份變量,各線程間同時訪問互不影響。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69939.html
摘要:線程安全問題都是由全局變量及靜態變量引起的。常量始終是線程安全的,因為只存在讀操作。局部變量是線程安全的。有狀態對象,就是有實例變量的對象,可以保存數據,是非線程安全的。 前言 有多少人在使用Spring框架時,很多時候不知道或者忽視了多線程的問題? ??因為寫程序時,或做單元測試時,很難有機會碰到多線程的問題,因為沒有那么容易模擬多線程測試的環境。那么當多個線程調用同一個bean的時...
摘要:線程安全問題都是由全局變量及靜態變量引起的。常量始終是線程安全的,因為只存在讀操作。局部變量是線程安全的。有狀態對象,就是有實例變量的對象,可以保存數據,是非線程安全的。 前言 有多少人在使用Spring框架時,很多時候不知道或者忽視了多線程的問題? ??因為寫程序時,或做單元測試時,很難有機會碰到多線程的問題,因為沒有那么容易模擬多線程測試的環境。那么當多個線程調用同一個bean的時...
摘要:將與當前線程建立一對一關系的值移除。為了讓方法里的操作具有原子性,也就是在一個線程執行這一系列操作的同時禁止其他線程執行這些操作,提出了鎖的概念。 上頭一直在說以線程為基礎的并發編程的好處了,什么提高處理器利用率啦,簡化編程模型啦。但是磚家們還是認為并發編程是程序開發中最不可捉摸、最詭異、最扯犢子、最麻煩、最惡心、最心煩、最容易出錯、最不符合社會主義核心價值觀的一個部分~ 造成這么多最...
摘要:但是還有另外的功能看的后一半代碼作用就是掃描位置之后的數組直到某一個為的位置,清除每個為的,所以使用可以降低內存泄漏的概率。 在涉及到多線程需要共享變量的時候,一般有兩種方法:其一就是使用互斥鎖,使得在每個時刻只能有一個線程訪問該變量,好處就是便于編碼(直接使用 synchronized 關鍵字進行同步訪問),缺點在于這增加了線程間的競爭,降低了效率;其二就是使用本文要講的 Threa...
摘要:每個線程中都有一個自己的類對象,可以將線程自己的對象保持到其中,各管各的,線程可以正確的訪問到自己的對象。。但一般來說線程共享的對象通過設置為某類的靜態變量就可以實現方便的訪問了,似乎沒必要放到線程中。 一篇老文章,引用自:http://www.iteye.com/topic/103804 首先,ThreadLocal 不是用來解決共享對象的多線程訪問問題的,一般情況下,通過...
閱讀 810·2021-11-22 15:25
閱讀 1408·2021-09-08 09:45
閱讀 1685·2021-09-02 09:46
閱讀 1299·2019-08-30 15:56
閱讀 1528·2019-08-29 15:14
閱讀 1159·2019-08-29 13:06
閱讀 2010·2019-08-29 12:34
閱讀 1400·2019-08-26 12:14