java中的全局变量如何实现?ThreadLocal~

  全局变量就是不管你在哪里,都能够直接引用的变量,还不用担心各种问题。每个语言都有自己的全局变量,我想!

  一般地,面向过程的语言当中,可能就是一个声明在最前面的变量,后面的代码直接引用,就成了全局变量!(最经典的C就是这样的)

如:js 中:

复制代码
var a = "hello,a!";

alert(a);

function fn1() {
    var b = "hello, b!"
    alert("global var a: " + a);
}

fn1();
复制代码

 但是也有的语言是不允许直接引用的,如PHP:(以下代码是会报错的,因为php中不允许函数中直接引用全局变量)

复制代码
<?php 
    $a = "hello, a!";
    echo $a . "\n";
    
    function fn1() {
        $b = "hello, b!";
        echo "global a is:" . $a . "\n";
    }
    
    fn1();
复制代码

需要加上 global关键词才行,php这么做的目的在于其没有规定的入口函数,不使用全局变量从而避免变量污染:

复制代码
<?php

$a = "hello, a!";
echo $a . "\n";

function fn1() {
    global $a;
    $b = "hello, b!";
    echo "global a is:" . $a . "\n";
}

fn1();
复制代码

 但是要在java中实现全局变量,可就没这么简单了。不是因为访问一个全局变量有问题,而是访问全局可变变量时,往往会引发线程安全问题,那么就不能够随便用全局变量了。

public class Constants {
    public static String CONST_6 = "6";
}

在需要使用的地方,直接使用 Constants.CONST_6 = 7; 就行了。但是因为java天生就是多线程环境,假如再来一个线程也更改这个变量,那么就出问题了。同等情况下,其他语言则往往是多进程环境,不必考虑变量的线程安全问题。

当然了,java自然是考虑到有需要访问全局变量的需求的,所以有了,ThreadLocal,这个类就是保证了线程安全的,可以作为全局变量使用的。

复制代码
public class GlobalVarManager {
    private static ThreadLocal<GlobalVars> globalVars = new ThreadLocal<>();

    public static GlobalVars getGlobalVars() {
        return globalVars.get();
    }

    public static void setGlobalVars(GlobalVars conn) {
        globalVars.set(conn);
    }
}
复制代码

如上方法,在外面使用 set, get 方式,就可以做到全局变量共享了,还保证了线程安全。

ThreadLocal的操作有三个set,get,remove,其实现原理为,使用一个map存放变量,将该map放到当前线程中:

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
复制代码
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }
复制代码
     public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

ThreadLocal 对于一般的开发工作,用处不一定很多,但是对于框架一类操作就比较有用了。

posted @   阿牛20  阅读(32935)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示