亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

ThreadLocal 解決多線程變量共享問題

gplane / 1982人閱讀

摘要:設(shè)置當(dāng)前線程的局部變量副本的變量值為指定值。示例首先,我們來看看不考慮多線程共享數(shù)據(jù)的情況。使用保存對象的局部變量。各線程間同時(shí)操作自己的變量,相互間沒有影響。采用以空間換時(shí)間方式,為每一個(gè)線程都提供一份變量,各線程間同時(shí)訪問互不影響。

版權(quán)聲明:本文由吳仙杰創(chuàng)作整理,轉(zhuǎn)載請注明出處:https://segmentfault.com/a/1190000009236777

1. ThreadLocal

ThreadLocal 不是一個(gè)線程,而是一個(gè)線程的本地化對象。當(dāng)某個(gè)變量在使用 ThreadLocal 進(jìn)行維護(hù)時(shí),ThreadLocal 為使用該變量的每個(gè)線程分配了一個(gè)獨(dú)立的變量副本,每個(gè)線程可以自行操作自己對應(yīng)的變量副本,而不會(huì)影響其他線程的變量副本。

2. API 方法

ThreadLocal 的 API 提供了如下的 4 個(gè)方法。

1)protected T initialValue()

返回當(dāng)前線程的局部變量副本的變量初始值。

2)T get()

返回當(dāng)前線程的局部變量副本的變量值,如果此變量副本不存在,則通過 initialValue() 方法創(chuàng)建此副本并返回初始值。

3)void set(T value)

設(shè)置當(dāng)前線程的局部變量副本的變量值為指定值。

4)void remove()

刪除當(dāng)前線程的局部變量副本的變量值。

在實(shí)際使用中,我們一般都要重寫 initialValue() 方法,設(shè)置一個(gè)特定的初始值。

2.1 示例

首先,我們來看看不考慮多線程共享數(shù)據(jù)的情況。

現(xiàn)在有小明、小剛、小紅三人在同一家銀行,分別向各自賬戶存入 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 + "--當(dāng)前賬戶余額為:" + this.money);
        this.money += money;
        System.out.println(threadName + "--存入 " + money + " 后賬戶余額為:" + this.money);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

運(yùn)行結(jié)果:

小明--當(dāng)前賬戶余額為:1000
小紅--當(dāng)前賬戶余額為:1000
小紅--存入 200 后賬戶余額為:1400
小剛--當(dāng)前賬戶余額為:1000
小剛--存入 200 后賬戶余額為:1600
小明--存入 200 后賬戶余額為:1200

結(jié)果是除了小明存錢和自己賬戶余額能對上外,小剛和小紅也都只存了 200,但他們的賬戶余額分別多了 200 和 400?

這是因?yàn)槎鄠€(gè)線程共享了同一個(gè)實(shí)例對象的局部變量所致。

使用 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
    ThreadLocal account = ThreadLocal.withInitial(new Supplier() {
        @Override
        public Integer get() {
            return 1000;
        }
    });

    public void deposit(int money) {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + "--當(dāng)前賬戶余額為:" + account.get());
        account.set(account.get() + money);
        System.out.println(threadName + "--存入 " + money + " 后賬戶余額為:" + account.get());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

運(yùn)行結(jié)果:

小明--當(dāng)前賬戶余額為:1000
小紅--當(dāng)前賬戶余額為:1000
小紅--存入 200 后賬戶余額為:1200
小剛--當(dāng)前賬戶余額為:1000
小剛--存入 200 后賬戶余額為:1200
小明--存入 200 后賬戶余額為:1200

可以看到,我們要的效果達(dá)到了。各線程間同時(shí)操作自己的變量,相互間沒有影響。

3. ThreadLocal 與 Thread 同步機(jī)制的比較

同步機(jī)制采用了以時(shí)間換空間方式,通過對象鎖保證在同一個(gè)時(shí)間,對于同一個(gè)實(shí)例對象,只有一個(gè)線程訪問。

ThreadLocal 采用以空間換時(shí)間方式,為每一個(gè)線程都提供一份變量,各線程間同時(shí)訪問互不影響。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/69939.html

相關(guān)文章

  • 如何看待Spring下單例模式與線程安全的矛盾

    摘要:線程安全問題都是由全局變量及靜態(tài)變量引起的。常量始終是線程安全的,因?yàn)橹淮嬖谧x操作。局部變量是線程安全的。有狀態(tài)對象,就是有實(shí)例變量的對象,可以保存數(shù)據(jù),是非線程安全的。 前言 有多少人在使用Spring框架時(shí),很多時(shí)候不知道或者忽視了多線程的問題? ??因?yàn)閷懗绦驎r(shí),或做單元測試時(shí),很難有機(jī)會(huì)碰到多線程的問題,因?yàn)闆]有那么容易模擬多線程測試的環(huán)境。那么當(dāng)多個(gè)線程調(diào)用同一個(gè)bean的時(shí)...

    dinfer 評(píng)論0 收藏0
  • 如何看待Spring下單例模式與線程安全的矛盾

    摘要:線程安全問題都是由全局變量及靜態(tài)變量引起的。常量始終是線程安全的,因?yàn)橹淮嬖谧x操作。局部變量是線程安全的。有狀態(tài)對象,就是有實(shí)例變量的對象,可以保存數(shù)據(jù),是非線程安全的。 前言 有多少人在使用Spring框架時(shí),很多時(shí)候不知道或者忽視了多線程的問題? ??因?yàn)閷懗绦驎r(shí),或做單元測試時(shí),很難有機(jī)會(huì)碰到多線程的問題,因?yàn)闆]有那么容易模擬多線程測試的環(huán)境。那么當(dāng)多個(gè)線程調(diào)用同一個(gè)bean的時(shí)...

    劉永祥 評(píng)論0 收藏0
  • Java并發(fā)編程之原子性操作

    摘要:將與當(dāng)前線程建立一對一關(guān)系的值移除。為了讓方法里的操作具有原子性,也就是在一個(gè)線程執(zhí)行這一系列操作的同時(shí)禁止其他線程執(zhí)行這些操作,提出了鎖的概念。 上頭一直在說以線程為基礎(chǔ)的并發(fā)編程的好處了,什么提高處理器利用率啦,簡化編程模型啦。但是磚家們還是認(rèn)為并發(fā)編程是程序開發(fā)中最不可捉摸、最詭異、最扯犢子、最麻煩、最惡心、最心煩、最容易出錯(cuò)、最不符合社會(huì)主義核心價(jià)值觀的一個(gè)部分~ 造成這么多最...

    instein 評(píng)論0 收藏0
  • Java 線程(7): ThreadLocal 的應(yīng)用及原理

    摘要:但是還有另外的功能看的后一半代碼作用就是掃描位置之后的數(shù)組直到某一個(gè)為的位置,清除每個(gè)為的,所以使用可以降低內(nèi)存泄漏的概率。 在涉及到多線程需要共享變量的時(shí)候,一般有兩種方法:其一就是使用互斥鎖,使得在每個(gè)時(shí)刻只能有一個(gè)線程訪問該變量,好處就是便于編碼(直接使用 synchronized 關(guān)鍵字進(jìn)行同步訪問),缺點(diǎn)在于這增加了線程間的競爭,降低了效率;其二就是使用本文要講的 Threa...

    shadajin 評(píng)論0 收藏0
  • 正確理解ThreadLocal

    摘要:每個(gè)線程中都有一個(gè)自己的類對象,可以將線程自己的對象保持到其中,各管各的,線程可以正確的訪問到自己的對象。。但一般來說線程共享的對象通過設(shè)置為某類的靜態(tài)變量就可以實(shí)現(xiàn)方便的訪問了,似乎沒必要放到線程中。 一篇老文章,引用自:http://www.iteye.com/topic/103804 首先,ThreadLocal 不是用來解決共享對象的多線程訪問問題的,一般情況下,通過...

    liangzai_cool 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<