全局變量就是不管你在哪里,都能夠直接引用的變量,還不用擔心各種問題。每個語言都有自己的全局變量,我想!
一般地,面向過程的語言當中,可能就是一個聲明在最前面的變量,后面的代碼直接引用,就成了全局變量!(最經典的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 對於一般的開發工作,用處不一定很多,但是對於框架一類操作就比較有用了。