开发工具与关键技术:Eclipse 10、java
作者:梁添荣
撰写时间:2020-06-08
有时候,在项目中难免会用到全局变量,但,当全局变量有多个线程操作该变量的时候,例如赋值和读取,就有可能出现数据混乱,出现读取到的是另一个线程设置的值,例如以下代码:
Controller层代码:
@RequestMapping(“Test”)
public class Test{
String str; //全局变量
@RequestMapping(“toTest”)
public String toTest() {
return “/test”;
}
@ResponseBody
@RequestMapping(“one”)
protected void one() {//第一个请求
str=“一”;
System.err.println(“是否等于一:”+str);
}
@ResponseBody
@RequestMapping(“twe”)
protected void twe() {//第二个请求
str=“二”;
System.out.println(“验证:”);
System.err.println(“是否等于二:”+str);
}
@ResponseBody
@RequestMapping(“tree”)
protected void tree() {//第三个请求
str=“三”;
System.err.println(“是否等于三:”+str);
}
}
页面层代码同时请求controller层的3个方法:
.
p
o
s
t
(
′
.post('
.post(′{ctx}/Test/one.do’,function(data){//第一个请求
},“json”);
.
p
o
s
t
(
"
.post("
.post("{ctx}/Test/twe.do",function(data){//第二个请求
},“json”);
.
p
o
s
t
(
"
.post("
.post("{ctx}/Test/tree.do",function(data){//第三个请求
},“json”);
这样的全局变量str就会引起数据混乱,如执行controller层的三个方法后,
输出的结果如下图:
(图一)
这是在第二个方法断点这两个输出
System.out.println(“验证:”);
System.err.println(“是否等于二:”+str);
(图二)
方法所测试出来的结果,本来在第二个方法里给str赋值为二,但因为断点这两个输出,
还没执行这处代码,str的值又被第三个方法赋值为三了,调试断点输出,和我们想象中str输出为二,但其实是输出str为三,str说明已经被赋值为三了。
造成这样的问题就是因为全局变量被多个线程读写操作而出现导致str输出的结果不确定。我们可以利用ThreadLocal来解决此问题:
使用方法:例
声明为:ThreadLocal str = new ThreadLocal();
赋值str.set(“值”);
取值为str.get()
即把controller层的代码修改为如下:
public class Test{
ThreadLocal str = new ThreadLocal();
@RequestMapping("toTest")
public String toTest() {
return "/test";
}
@ResponseBody
@RequestMapping("one")
protected void one() {//第一个请求
str.set("一");
System.err.println("是否等于一:"+str.get());
}
@ResponseBody
@RequestMapping("twe")
protected void twe() {//第二个请求
str.set("二");
System.out.println("验证:");
System.err.println("是否等于二:"+str.get());
}
@ResponseBody
@RequestMapping("tree")
protected void tree() {//第三个请求
str.set("三");
System.err.println("是否等于三:"+str.get());
}
}
图三图四就是断点测试后不会出现数据混乱了:
(图三断点)
(图四:第二个方法输出str为二了)
总结:项目尽量少用全局变量,使用也要考虑并发问题。