多线程情况下,很容发生线程安全问题,那么我们在程序中应该怎样避免呢?
1>全局变量使用final修饰
像Integer,String这样的类其实都是用final修饰的,比如我们在代码中这样声明一个全局变量int a = 0;那么这个变量接下来是不能被更改的,否则编译会报错,但是final修饰的Map,值却可以被修改,所以说HashMap是线程不安全的!
2>堆栈封闭:局部变量,无并发问题
从java内存模型来看,多线程情况下每个线程会克隆一份当前局部变量的副本到自己线程内进行修改,所以不存在
多个线程同时操作一个变量的情况,继而不会引发线程安全问题,局部变量在我们的代码中是最经常用的,其实我们一直在写线程安全的代码
3>ThreadLocal--线程安全
类似一个map,key为当前线程的名称,value为我们本地自己存的值,该值可在线程存活期间在任何地方被共用!
典型的例子:如Cookie,可以将Cookie在拦截器中存入ThreadLocal,在其他接口中如果需要Cookie则可以通过ThrreadLocal进行获取,再比如数据库连接Connection,必须保证多线程下的安全性,也是可以用ThreadLocal解决
4>线程不安全的类:如StringBuilder,SimpleDateFormat,ArrayList,HashMap(若用作局部变量,还是线程安全的)
线程安全的类:如StringBuffer(内部方法都用sychonized修饰,但是效率不如StringBuilder),,stack,vector,HashTable
5>容器安全
ArrayList----->CopyOnWriteArrayList
HashSet,TreeSet----->CopyOnWriteArraySet,ConcurrentSkipListSet
HashMap,TreeMap--->ConcurrentHashMap,ConcurrentSkipListMap
推荐容器安全的一种写法(全局):
Collections.synchronizedList(new ArrayList<>());
Collections.synchronizedMap(new HashMap<String,Object>());