前言
早在刚开始学习java se的时候,就遇到过这样问题,xxx是线程安全的,xxxx是线程不安全的,当时也是一脸蒙,只记住了结论。后来接触了单例才有一点了解
线程安全的:
vector、hashtable、stringbuffer等
非线程安全的:
arraylist、linkedlist、hashmap、StringBuilder等等
首先来模拟一个案例
测试集合类
自定义线程
测试类:
测试结果:
99873
99968
99955
100000
100000
100000
100000
Exception in thread “Thread-7516” java.lang.ArrayIndexOutOfBoundsException: 76327
at java.util.ArrayList.add(ArrayList.java:441)
at com.zwl.test.Mythread.run(Mythread.java:20)
at java.lang.Thread.run(Thread.java:744)
有时不会出现异常,但是list的长度不是最终期望的那样,显然是线程不安全的,
这里是arraylist,同样将其换成linkedlist,也可以改变list,变成其它,得到同样线程不安全结果
测试结果:
100000
99783
100000
99945
99897
99996
99879
99971
100000
99899
将其换成线程安全的,如
List
测试结果:
100000
100000
100000
100000
100000
100000
100000
100000
100000
100000
当然集合中的线程不安全是多线程同时操作同一个对象,如果是不同类,就不存在线程安全问题
对于线程安全,一般通过线程同步来实现,即通过申明synchronized关键字
如,改一下之前的线程安全的例子number类
修改后的number类
然后是自定义线程
线程测试类
测试类:
测试结果:
100000
100000
100000
100000
99940
99300
100000
100000
100000
100000
出现了线程不安全
可以通过对方法声明同步
public synchronized void count(){}
最后输出的书都是同一个数
最后不得不说,线程安全是一个很复杂的问题,有时候不注意就会出现数据上的各种问题!!!