美文网首页JavaJava多线程专题
[Java多线程编程之六] 线程封闭

[Java多线程编程之六] 线程封闭

作者: 小胡_鸭 | 来源:发表于2019-10-21 22:42 被阅读0次

一、什么是线程封闭?

  多线程访问共享可变数据时,线程间执行顺序的不同可能导致程序运行结果的不同,即线程安全问题;所以在多线程环境下,不涉及到共享的数据,就要通过线程封闭防止数据被共享修改,将数据封闭在各自的线程之中,这种避免同步的技术就是线程封闭

二、线程封闭的实现

1、ThreadLocal

  ThreadLocal是Java中一种特别的线程级别的变量,当线程访问时,会为每个线程创建一个变量的副本,副本之间彼此独立,互不影响,从代码上看不同线程访问的是同一个变量,但实际上不同线程访问ThreadLocal时,获取到的封装其中的数据存储在不同的内存中,这保证了线程安全,代码示例如下:

// 线程封闭示例
public class Demo7 {
    /** threadLocal变量,每个线程都有一个副本,互不干扰 */
    public static ThreadLocal<String> value = new ThreadLocal<String>();
    
    public void threadLocalTest() throws Exception {        
        value.set("这是主线程设置的123");       // 主线程设置值
        String v = value.get();
        System.out.println("线程1执行之前,主线程取到的值:" + v);
        
        new Thread(new Runnable() {
            @Override
            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();
    }
}

【代码解析】代码中有两个线程:主线程和匿名线程(姑且将其称为线程1),主线程率先访问ThreadLocal变量并设置其包装的String对象的值为 这是主线程设置的123 打印输出设置后的效果;接着执行线程1,线程1也去访问ThreadLocal,但是它拿到的数据值是空的,因为此时JVM为线程1中的ThreadLocal包装的数据分配了一个新的内存,接着线程1设置值并打印出来;线程1执行结束后,回到主线程,打印出来的值依然是执行线程1前主线程设置的值,说明两个线程对ThreadLocal的读取和设置操作是隔离的,互不影响。

执行结果:


如何理解ThreadLocal是一种线程级别的变量?

  每个线程都会有自己的栈,正常情况下多个线程访问一个共享对象时,是在自己的栈中持有对这个对象的引用,指向堆内存中的内存对象,如图所示:



  而当线程访问的是ThreadLocal时,ThreadLocal会为每个线程单独创建一个对象,不同线程对持有的对象进行操作互不干扰,也无法通过线程发布,是一种绝对安全的线程隔离,保证线程安全,如图所示:



  从某种程度上看,ThreadLocal可以看成是线程跟数据对象映射的Map,即Map<Thread, T>,每个线程读取数据时就通过当前线程去map里面get,从这个角度看,
threadLocal.get() = map.get(Thread.currentThread())
threadLocal.set(obj) = map.put(Thread.currentThread(), obj)
2、局部变量

  局部变量被封闭在线程的栈中,而线程栈是属于线程私有的内存区域,因此其他线程无法访问,从而保证线程安全,常见的局部变量有方法中的局部变量,循环中的局部变量等。

public void fun() {
    String str = ...;
}

while (true) {
    String str = ...;
}

for (int i = 0; i < length: i++) {
    int j = ...;
}

相关文章

  • Java多线程目录

    Java多线程目录 Java多线程1 线程基础Java多线程2 多个线程之间共享数据Java多线程3 原子性操作类...

  • [Java多线程编程之六] 线程封闭

    一、什么是线程封闭?   多线程访问共享可变数据时,线程间执行顺序的不同可能导致程序运行结果的不同,即线程安全问题...

  • 带你搞懂Java多线程(四)

    带你搞懂Java多线程(一)带你搞懂Java多线程(二)带你搞懂Java多线程(三) 什么是线程间的协作 线程之间...

  • 多线程--基础

    Java多线程 从本篇开始,笔者开始了一个新的专题,来说说Java多线程。 在讲解Java多线程之前,我们来了解下...

  • Java多线程

    Java多线程 从本篇开始,笔者开始了一个新的专题,来说说Java多线程。 在讲解Java多线程之前,我们来了解下...

  • iOS多线程相关面试题

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • 多线程之--NSOperation

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • iOS多线程之--NSThread

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • 多线程编程

    多线程编程之Linux环境下的多线程(一)多线程编程之Linux环境下的多线程(二)多线程编程之Linux环境下的...

  • 我看谁还不懂多线程之间的通信+基础入门+实战教程+详细介绍+附源

    一、多线程之间的通信(Java版本) 1、多线程概念介绍 多线程概念 在我们的程序层面来说,多线程通常是在每个进程...

网友评论

    本文标题:[Java多线程编程之六] 线程封闭

    本文链接:https://www.haomeiwen.com/subject/zemmmctx.html