码迷,mamicode.com
首页 > 其他好文 > 详细

ThreadLocal使用总结

时间:2020-12-22 12:50:12      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:err   class   一个   变量   within   有一个   print   cut   通过   

一、ThreadLocal基本使用

1.1使用场景

不同的线程对全局变量进行修改,使用ThreadLocal后会为每个线程创建一个副本,而不会影响其他线程的副本,确保了线程的安全

  private static ThreadLocal<Integer> localvariable=ThreadLocal.withInitial(()->1);
    public static void main(String[] args) {
        Thread threadOne=new Thread(new Runnable() {
            @Override
            public void run() {
                Integer integer = localvariable.get();
                localvariable.set(++integer);
                System.out.println("线程1: "+localvariable.get());
            }
        });
        Thread threadTwo=new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程2: "+localvariable.get());
            }
        });
        System.out.println("主线程: "+localvariable.get());
        threadOne.start();
        threadTwo.start();
    }

运行结果:

主线程: 1
线程1: 2
线程2: 1

线程1的修改没有影响到线程2的读取,保证了线程的安全

场景二

类似于全局变量,但是不想被多个线程进行共享

    private static Integer count=0;
    private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            Runnable runnable = new Runnable(){
                @Override
                public void run() {
                    System.out.println(count);
                }
            };
            fixedThreadPool.execute(runnable);
        }
        count++;
    }

像如上代码,本来是想所有线程都输出初始的count,当主线程累加后,剩下的线程输出的值就变成了1

以上代码执行的结果:

0
0
0
0
1
1
1
1
1
1

那么我们可以用ThreadLocal将原始的全局变量进行保存然后传参给其他的线程,这样就获取的是原始的全局变量

 private static Integer count=0;
    private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
    private static ThreadLocal<Integer> local=new ThreadLocal();
    public static void main(String[] args) {
        local.set(count);
        for(int i=0;i<10;i++){
            Integer localCount = local.get();
            Runnable runnable = new Runnable(){
                @Override
                public void run() {
                    System.out.println(localCount);
                }
            };
            fixedThreadPool.execute(runnable);
        }
        count++;
    }

0
0
0
0
0
0
0
0
0
0

1.2 原理分析

技术图片

 

 

threadLocals = null;
inheritableThreadLocals = null;

Thread类中有一个threadLocals和一个inheritableThreadLocals,他们都是ThreadLocalMap 类型的变量,默认都为null

当第一次调用set方法的时候创建

void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

将每个线程的本地变量存放在threadLocals变量中,如果调用线程一直不终止,那么这个本地变量会一直存放在调用线程的ThreadLocals变量里面,所以当不使用本地变量是可以通过调用ThreadLocal变量的remove方法,从当前线程的threadLocals

里面删除该本地变量。

 

技术图片

 

 

ThreadLocal 是JDK 包提供的,它提供了线程本地变量,也就是如果你创建了一个
ThreadLocal 变量,那么访问这个变量的每个线程都会有这个变量的一个本地副本。当多
个线程操作这个变量时,实际操作的是自己本地内存里面的变量,从而避免了线程安全问

 

ThreadLocal使用总结

标签:err   class   一个   变量   within   有一个   print   cut   通过   

原文地址:https://www.cnblogs.com/anyanpeng/p/14151474.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!