• java线程——线程局部变量


    一,线程局部变量ThreadLocal的作用

      用于实现线程内部的数据共享,既对于相同的程序代码,多个模块在同一个线程中运行时要共享一份数据,在另一个线程访问的时候,访问的由是另一份数据

      每个线程调用ThreadLocal对象的set方法时,就相当于向内部Map集合中增加一条记录。

      Map(key,value)key相当于当前的线程,value相当于set()传递进来的值。

      ThreadLocal<T> threadLocal =new ThreadLocal<T>();  T是set()方法传进来的值类型。

    问题:一个ThreadLocal中只能存放一个变量,既其中只能存放一个数据,如果由两个数据,可以定义两个ThreadLocal,但是如果有多个呢?例如100个?

      解决方法是定义一个对象来存放这100个数据,然后在ThreadLocal中存放这个对象。

    二,在 Runnable 中创建 ThreadLocal 

    在线程类内部创建 ThreadLocal,基本步骤如下: 

      ①、在多线程的类(如 ThreadDemo 类)中,创建一个 ThreadLocal 对象 threadXxx,用来保存线程间需要隔离处理的对象 xxx。

      ②、在 ThreadDemo 类中,创建一个获取要隔离访问的数据的方法 getXxx(),在方法中判断,若ThreadLocal 对象为 null 时候,应该 new()一个隔离访问类型的对象,并强制转换为要应用的类型

      ③、在 ThreadDemo 类的 run()方法中,通过调用 getXxx()方法获取要操作的数据,这样可以保证每个线程对应一个数据对象,在任何时刻都操作的是这个对象。 

      代码:

    package com.itheima.gan;
    
    import java.util.Random;
    
    public class ThreadLocalTest implements Runnable{
        //创建一个线程局部变量
        ThreadLocal<Student> studentThreadLocal=new ThreadLocal<Student>();
    
        @Override
        public void run() {
            //获取当前线程的名字
            String currentThreadName=Thread.currentThread().getName();
            System.out.println(currentThreadName+" is running ....");
            
            //随机生成一个整数
            Random random=new Random();
            int age=random.nextInt(100);
            
            System.out.println(currentThreadName+" is set age:"+age);
            //通过这个方法为每一个线程都设置一个独立的student对象
            Student student=getStudent();
            student.setAge(age);
            
            System.out.println(currentThreadName+" is first get age:"+student.getAge());
            
            //线程沉睡
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            //线程第二次获取年纪
            System.out.println(currentThreadName+" is second get age:"+student.getAge());
        }
    
        private Student getStudent() {
            //先获取studnet对象
            Student student=studentThreadLocal.get();
            //判断对象是否为空,是空的话表示没有给局部变量设置,如果是空的话就在给局部变量重新设置一个值
            if(student==null) {
                student=new Student();
                studentThreadLocal.set(student);
            }
            return student;
        }
        
        
        public static void main(String[] args) {
            ThreadLocalTest test=new ThreadLocalTest();
            
            Thread t1=new Thread(test,"线程1");
            Thread t2=new Thread(test,"线程2");
            
            t1.start();
            t2.start();
        }
        
        
    }
    class Student{
        int age;
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age=age;
        }
    }

      运行结果:

           

      

  • 相关阅读:
    Kafka2.0服务端写入和读取流程
    Kafka2.0服务端启动源码
    Kafka2.0消费者协调器源码
    Kafka2.0消费者客户端源码分析
    [六省联考2017]分手是祝愿 题解(期望dp)
    [信息学奥赛一本通oj1741]电子速度 题解
    [CSP-S模拟测试53]题解
    [CSP-S模拟测试52]题解
    [CSP-S模拟测试ex]题解
    [CSP-S模拟测试51]题解
  • 原文地址:https://www.cnblogs.com/zhilili/p/11978446.html
Copyright © 2020-2023  润新知