• java多线程详解(5)-Threadlocal用法


    转自:https://www.cnblogs.com/weiguo21/p/4755527.html

    ThreadLocal是什么

    早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。

    使用这个工具类可以很简洁地编写出优美的多线程程序。

    当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,

    所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

    从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。

    所以,在Java中编写线程局部变量的代码相对来说要笨拙一些,因此造成线程局部变量没有在Java开发者中得到很好的普及。

    ThreadLocal的接口方法

    ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:

    • void set(Object value)设置当前线程的线程局部变量的值。
    • public Object get()该方法返回当前线程所对应的线程局部变量。
    • public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
    • protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。

      

    在JDK5.0中,ThreadLocal已经支持泛型,该类的类名已经变为ThreadLocal<T>。API方法也相应进行了调整,

    新版本的API方法分别是void set(T value)、T get()以及T initialValue()。

     下面将用一段代码展示ThreadLocal类的功能

    复制代码
    package com.cary.base.thread;
    
    import java.util.Random;
    
    /**
     * ThreadLocal测试
     * 
     * @author cary
     * @date 2015-8-24-下午6:06:01
     * @version 1.0.0
     */
    public class ThreadLocalTest {
        private static ThreadLocal<Integer> x = new ThreadLocal<Integer>();
    
        public static void main(String[] args) {
            for (int i = 0; i < 2; i++) {
                new Thread(new Runnable() {
                    public void run() {
                        int data = new Random().nextInt();
                        System.out.println(Thread.currentThread().getName()
                                + " has put data :" + data);
                        x.set(data);
    
                        new A().get();
                        new B().get();
                    }
                }).start();
            }
        }
    
        /**
         * 获取数据
         * 
         * @author cary
         * @date 2015-8-24-下午6:05:27
         * @version 1.0.0
         */
        static class A {
            public void get() {
                int data = x.get();
                System.out.println("A from " + Thread.currentThread().getName()
                        + " get data :" + data);
    
            }
        }
    
        /**
         * 获取数据
         * 
         * @author cary
         * @date 2015-8-24-下午6:05:44
         * @version 1.0.0
         */
        static class B {
            public void get() {
                int data = x.get();
                System.out.println("B from " + Thread.currentThread().getName()
                        + " get data :" + data);
    
            }
        }
    }
    复制代码

    运行结果:

    复制代码
    Thread-0 has put data :-889773907
    Thread-1 has put data :-514366238
    A from Thread-0 get data :-889773907
    A from Thread-1 get data :-514366238
    B from Thread-1 get data :-514366238
    B from Thread-0 get data :-889773907
    复制代码

    可以看到每个线程get()到的都是自己set()进去的值

    我们写程序过程中经常有这样的代码

    复制代码
        private final static ThreadLocal<SystemUser> userThreadLocal = new ThreadLocal<SystemUser>();
        
        @Autowired
        private SystemLogService systemLogService;
    
        /**
         * 设置当前用户
         * 
         * @author cary
         * @param user
         */
        public void setCurrentSystemUser(SystemUser user) {
            userThreadLocal.set(user);
        }
        /**
         * 从本地线程中取当前用户
         * 
         * @author cary
         * @return 系统用户
         */
        public SystemUser getCurrentSystemUser() {
            SystemUser user = userThreadLocal.get();
            if (null == user) {
                user = (SystemUser) SecurityUtils.getSubject().getPrincipal();
            }
    
            return user;
        }
    复制代码

    小结:

    ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。

    在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。

  • 相关阅读:
    【JAVA Swing】自定义弹出的无边提醒框(可自动消失)
    java比较器Comparator的简单使用
    BoneCP的简单使用
    鸿蒙的js开发部模式18:鸿蒙的文件上传到python服务器端
    【知识点前情提要】鸿蒙小白入门指南!跟着张荣超老师学鸿蒙
    分布式流转开发常见报错FAQ
    Ability之间或者进程间数据传递之对象(Sequenceable序列化)
    【资源下载】安卓VS鸿蒙第三方件切换宝典 V1.0
    鸿蒙开源第三方组件 ——B站开源弹幕库引擎的迁移(上)
    鸿蒙的js开发部模式17:鸿蒙的系统能力的应用模块
  • 原文地址:https://www.cnblogs.com/sharpest/p/10884825.html
Copyright © 2020-2023  润新知