专栏首页编程坑太多JAVA线程之ThreadLocal与栈封闭(六)

JAVA线程之ThreadLocal与栈封闭(六)

(一)线程封闭概念

  • ① 引言

多线程访问共享可变数据,共享变量,涉及到线程间数据同步的问题。一般很多不会去用到共享数据,所以提出了线程封闭的概念。

  • ② 定义

数据都被封闭在各自的线程之中,就不需要同步,也不用考虑线程的安全,这种通过数据封闭在线程中而避免使用同步的技术被称为线程封闭。

  • ③ 实现体现

ThreadLocal,局部变量

  • ④ ThreadLocal

它是一个线程级别变量,每个线程都有一个ThreadLocal就是每个线程拥有了自己独立的一个变量,竞争条件被彻底消除了,在并发模式下是绝对安全的变量。

用法:ThreadLocal<T> threadVar = new ThreadLocal<T>(); 会自动在每个线程上创建一个T的副本,副本之间彼此独立,互不影响,可以用TheadLocal存储一些参数,以便在线程中多个方法中使用,用来代替方法传参的做法。

其实也不难理解,JVM维护了一个Map<Thread,T>,每个线程要用这个T的时候,用以前的线程去Map里面取。仅作为一个概念理解。

  • ⑤ 源码
/** 线程封闭示例 */
public class Demo7 {
    /** threadLocal变量,每个线程都有一个副本,互不干扰 */
    public static ThreadLocal<String> value = new ThreadLocal<String>();

    /**
     * threadlocal测试
     *
     * @throws Exception
     */
    public void threadLocalTest() throws Exception {

        // threadlocal线程封闭示例
        value.set("这是主线程设置的123"); // 主线程设置值
        String v = value.get();
        System.out.println("线程1执行之前,主线程取到的值:" + v);

        new Thread(new Runnable() {
            public void run() {
                String v = value.get();
                System.out.println("线程1取到的值:" + v);
                // 设置 threadLocal
                value.set("这是线程1设置的456");

                v = value.get();
                System.out.println("重新设置之后,线程1取到的值:" + v);
                System.out.println("线程1执行结束");
            }
        }).start();

        Thread.sleep(5000L); // 等待所有线程执行结束

        v = value.get();
        System.out.println("线程1执行之后,主线程取到的值:" + v);

    }

    public static void main(String[] args) throws Exception {
        new Demo7().threadLocalTest();
    }
}

主线程set了 value =【这是主线程设置的123】,直接在子线程中取取不到的,但是子线程自己设置后,自己来取,取出来就是自己设置的 value = 【这是线程1设置的456】,虽然子线程已经赋值了,但是从主线程来取,取出来的还是主线程赋的值【这是主线程设置的123】,它们之间各玩各的互相不干扰。

(二)栈封闭

就是使用局部变量,局部变量的固有属性之一就是封闭在线程中。他们位于执行线程的栈中,其他线程无法访问这个栈。

PS:这次说了线程封闭的概念,其实很容易理解只要知道在ThreadLocal是JVM内部维护了一个Map就可以了。栈封闭没有纤细概述,跟局部变量是一个概念。

本文分享自微信公众号 - 编程坑太多(idig88),作者:诸葛阿明

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 『互联网架构』软件架构-RPC网络传输原理与实现(45)

    IT故事会
  • JAVA线程之线程池(七)

    1.不一定是越多越好,首先线程在java里面是一个对象,只要是对象肯定要占用一定的资源,更多的是操作系统保护的资源,线程的创建和销毁都需要时间和空间,如果线程的...

    IT故事会
  • Java中的锁以及sychronized实现机制(十)

    PS:有数据表明,除去大型互联网公司,80%的系统不存在多线程的竞争的情况,一定要熟悉这几种锁,对以后面试镀金(面试)真的很有用。

    IT故事会
  • 高并发编程-ReentrantLock公平锁深入解析

    ReentrantLock是一个可重入的互斥锁,它不但具有synchronized实现的同步方法和同步代码块的基本行为和语义,而且具备很强的扩展性。Reentr...

    JavaQ
  • 线程池 ThreadPool

    在使用C++的经历中,经常使用多线程(计算密集型),也经常会思考要如何对多线程控制,但没有采用过线程池思想的实现。 在java并发的学习过程中,了解了Java...

    birdskyws
  • Java并发-守护线程-Daemon

     我们如上在main线程中定义了一个子线程t,将子线程的run方法写为sleep调用比main方法的sleep调用更久时间,以验证父类线程main的执行完毕并释...

    Fisherman渔夫
  • 线程池-线程池的好处

    在线程的销毁时需要回收这些系统资源。频繁的创建和销毁线程会浪费大量的系统资源,增加并发编程的风险。

    DougWang
  • Java的重入锁ReentrantLock

    ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该...

    用户3467126
  • 聊一聊Java中的线程池

    为了避免系统频繁地创建和销毁线程,我们可以让创建的线程进行复用。其实和数据库连接池是一样的道理,为了避免每次数据库查询都重新建立和销毁数据库连接,我们可以使用数...

    beifengtz
  • JVM最多支持多少个线程?

    (不要抱怨语法细节,这才刚刚开始)那你当然希望能得到成百上千个运行的线程。但是,创建一个线程的成本是相对较大的,(过多线程)调度的开销会变得突出。能否让这些线程...

    哲洛不闹

扫码关注云+社区

领取腾讯云代金券