欢迎使用CSDN-markdown编辑器
来源:互联网 发布:手机淘宝积分在那里看 编辑:程序博客网 时间:2024/06/05 04:33
最近在做项目时,看到这么一个代码。多线程会共同访问的一个类的方法,该类在调用时,所有的线程只会访问同一个实例对象,该类大概如下(非原码,参考用):
public class class1 { private Map<String, Object> map = new HashMap();; public void me1(String s){ map.clear(); map.put("me1", "me1"); map.put(s, s); System.out.println("调用者:"+s+":"+Thread.currentThread().getId()+":"+map); } public void me2(String s){ map.clear(); map.put("me2", "me2"); map.put(s, s); System.out.println("调用者:"+s+":"+Thread.currentThread().getId()+":"+map); } public void me3(String s){ map.clear(); map.put("me3", "me3"); map.put(s, s); System.out.println("调用者:"+s+":"+Thread.currentThread().getId()+":"+map); }}
可以看到,这个类成员中有一个Map集合,所有的方法都会访问这个map,在使用Map存值前调用clear方法清空。看上去像没什么问题,但是在多线程访问一个对象的时候,用M。这种是无法保证值的正确性。测试一下
public class test {
public static void main(String[] args) { final class1 c = new class1(); Thread t1 = new Thread(new Runnable() { @Override public void run() { c.me1("t1"); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { c.me2("t2"); } }); Thread t3 = new Thread(new Runnable() { @Override public void run() { c.me3("t3"); } });// for(int x=0;x<10;x++){ t1.start(); t2.start(); t3.start(); //}}
}
创建三个线程,分别访问调用这个对象的三个方法,结果如下:
结果1:
调用者:t2:11:{me2=me2, t2=t2}
调用者:t1:10:{me2=me2, t2=t2}
调用者:t3:12:{me2=me2, t2=t2}
结果2:
调用者:t1:10:{me3=me3, t3=t3}
调用者:t3:12:{me3=me3, t3=t3}
调用者:t2:11:{me3=me3, t3=t3}
很明显,在多线程访问时,值不对。
如果我每个线程都去new一个新的对象,结果肯定是对的。代码如下:
public class test {
public static void main(String[] args) {// final class1 c = new class1(); Thread t1 = new Thread(new Runnable() { @Override public void run() { class1 c = new class1(); c.me1("t1"); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { class1 c = new class1(); c.me2("t2"); } }); Thread t3 = new Thread(new Runnable() { @Override public void run() { class1 c = new class1(); c.me3("t3"); } });// for(int x=0;x<10;x++){ t1.start(); t2.start(); t3.start(); //}}
}
结果:
调用者:t3:12:{me3=me3, t3=t3}
调用者:t2:11:{me2=me2, t2=t2}
调用者:t1:10:{me1=me1, t1=t1}
这样数据也是对的,但是,这样在我的项目中肯定是不行的,因为公司框架的原因,只能去调用同一个对象。所以只能把类改掉,如下:
public class class1 {
public void me1(String s){ Map<String, Object> map = new HashMap(); map.clear(); map.put("me1", "me1"); map.put(s, s); System.out.println("调用者:"+s+":"+Thread.currentThread().getId()+":"+map);}public void me2(String s){ Map<String, Object> map = new HashMap(); map.clear(); map.put("me2", "me2"); map.put(s, s); System.out.println("调用者:"+s+":"+Thread.currentThread().getId()+":"+map);}public void me3(String s){ Map<String, Object> map = new HashMap(); map.clear(); map.put("me3", "me3"); map.put(s, s); System.out.println("调用者:"+s+":"+Thread.currentThread().getId()+":"+map);}
}
OK,这样基本就没问题了,调用方法的时候在方法里面去创建map集合,这样就能避免数据乱掉的问题。
阅读全文
0 0
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 视频项目笔记(2)
- MyBatis框架简单入门
- ionic工程引入cordova plugin camera 插件编译报错问题总结
- 数据库开发技术 课堂笔记8 处理并发
- mac gdb调试 解决warning: unhandled dyld version (15) [Inferior 1 (process 660) exited normally]
- 欢迎使用CSDN-markdown编辑器
- Codeforces Round #443 (Div. 2)
- DBCP数据库连接池的简单使用
- 效果图第二课笔记:几何体建模
- vue.js2.0完整视频教程12套
- ART GC ModUnionTable 实现及使用
- 每天回顾linux命令(pushd、pwd、popd)
- 参考博客
- is not allowed to connect to this MySQL server