验证ArrayList线程不安全,redisson提供的分布式集合线程安全
2018-03-22 17:38
781 查看
借鉴这篇文章的测试方法。一。.测试ArrayListpublic class TestList implements Runnable{
//线程不安全
private List threadList = new ArrayList();
//线程安全
//private List threadList = Collections.synchronizedList(new ArrayList());
@Override
public void run() {
try {
Thread.sleep(10);
}catch (InterruptedException e){
e.printStackTrace();
}
//把当前线程名称加入list中
threadList.add(Thread.currentThread().getName());
}
@Test
public void test() throws InterruptedException{
TestList listThread = new TestList();
for(int i = 0; i < 100; i++){
Thread thread = new Thread(listThread, "线程"+String.valueOf(i)); //线程名是 i
thread.start();
}
//等待子线程执行完
Thread.sleep(2000);
System.out.println(listThread.threadList.size());
//输出list中的值
for(int i = 0; i < listThread.threadList.size(); i++){
//如果元素是null 则换行,元素是null也会在控制台输出
if(listThread.threadList.get(i) == null){
System.out.println();;
}
System.out.print(listThread.threadList.get(i) + " ");
//输出结果是乱的,因为不一定哪个线程先把线程名放进集合
}
}
} 开一百个线程,把线程名加进集合,最后输出,如果集合元素是null 就换行。
输出结果有null或者数组越界异常说明 ArrayList 线程不安全。
原因是,ArrayList 的add方法分两步:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
1.size是当前元素的数量,判断集合大小是否允许再加一个元素,只要能允许再加一个,集合上限就不会增加
2.加一个元素
3.size++
如果线程1 执行完第二步,失去资源,线程2执行,由于size还没有++,线程2 的名称会覆盖集合中线程1 的名称,然后size+1,轮到线程1执行,size又+1.就会导致第二个元素是null。
如果线程1 执行到第一步,判断集合大小 刚好 可以再放下一个元素,暂停轮到 线程2 执行也判断可以加1元素,然后线程2把线程名称加入集合,size+1,线程1再加入元素 就已经越界了。
二。测试redisson 的RList<Object>
结果没有出现null和越界异常,说明RList是线程安全的。 线程安全主要体现在对数据的写,不会出现脏数据public class TestRedisson implements Runnable{
@Autowired
RedissonClient redissonClient;
private RList<Object> list;
@Override
public void run() {
try {
Thread.sleep(10);
}catch (InterruptedException e){
e.printStackTrace();
}
//把当前线程名称加入list中
list.add(Thread.currentThread().getName());
}
@Test
public void test() throws InterruptedException{
RList<Object> list = redissonClient.getList("list");
TestRedisson t=new TestRedisson();
t.setList(list);
for(int i = 0; i < 1000; i++){
Thread thread = new Thread(t, "线程"+String.valueOf(i)); //线程名是 i
thread.start();
}
//等待子线程执行完
Thread.sleep(2000);
System.out.println(t.getList().size());
//输出list中的值
for(int i = 0; i < t.getList().size(); i++){
//如果元素是null 则换行,元素是null也会在控制台输出
if(t.getList().get(i) == null){
System.out.println();;
}
System.out.print(t.getList().get(i) + " ");
//输出结果是乱的,因为不一定哪个线程先把线程名放进集合
}
}
//线程不安全
private List threadList = new ArrayList();
//线程安全
//private List threadList = Collections.synchronizedList(new ArrayList());
@Override
public void run() {
try {
Thread.sleep(10);
}catch (InterruptedException e){
e.printStackTrace();
}
//把当前线程名称加入list中
threadList.add(Thread.currentThread().getName());
}
@Test
public void test() throws InterruptedException{
TestList listThread = new TestList();
for(int i = 0; i < 100; i++){
Thread thread = new Thread(listThread, "线程"+String.valueOf(i)); //线程名是 i
thread.start();
}
//等待子线程执行完
Thread.sleep(2000);
System.out.println(listThread.threadList.size());
//输出list中的值
for(int i = 0; i < listThread.threadList.size(); i++){
//如果元素是null 则换行,元素是null也会在控制台输出
if(listThread.threadList.get(i) == null){
System.out.println();;
}
System.out.print(listThread.threadList.get(i) + " ");
//输出结果是乱的,因为不一定哪个线程先把线程名放进集合
}
}
} 开一百个线程,把线程名加进集合,最后输出,如果集合元素是null 就换行。
输出结果有null或者数组越界异常说明 ArrayList 线程不安全。
原因是,ArrayList 的add方法分两步:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
1.size是当前元素的数量,判断集合大小是否允许再加一个元素,只要能允许再加一个,集合上限就不会增加
2.加一个元素
3.size++
如果线程1 执行完第二步,失去资源,线程2执行,由于size还没有++,线程2 的名称会覆盖集合中线程1 的名称,然后size+1,轮到线程1执行,size又+1.就会导致第二个元素是null。
如果线程1 执行到第一步,判断集合大小 刚好 可以再放下一个元素,暂停轮到 线程2 执行也判断可以加1元素,然后线程2把线程名称加入集合,size+1,线程1再加入元素 就已经越界了。
二。测试redisson 的RList<Object>
结果没有出现null和越界异常,说明RList是线程安全的。 线程安全主要体现在对数据的写,不会出现脏数据public class TestRedisson implements Runnable{
@Autowired
RedissonClient redissonClient;
private RList<Object> list;
@Override
public void run() {
try {
Thread.sleep(10);
}catch (InterruptedException e){
e.printStackTrace();
}
//把当前线程名称加入list中
list.add(Thread.currentThread().getName());
}
@Test
public void test() throws InterruptedException{
RList<Object> list = redissonClient.getList("list");
TestRedisson t=new TestRedisson();
t.setList(list);
for(int i = 0; i < 1000; i++){
Thread thread = new Thread(t, "线程"+String.valueOf(i)); //线程名是 i
thread.start();
}
//等待子线程执行完
Thread.sleep(2000);
System.out.println(t.getList().size());
//输出list中的值
for(int i = 0; i < t.getList().size(); i++){
//如果元素是null 则换行,元素是null也会在控制台输出
if(t.getList().get(i) == null){
System.out.println();;
}
System.out.print(t.getList().get(i) + " ");
//输出结果是乱的,因为不一定哪个线程先把线程名放进集合
}
}
相关文章推荐
- Java arraylist线程不安全 vectory 线程安全
- 确保真正的线程安全——微软为什么不提供线程安全库
- ArrayList非线程安全、Vector线程安全原理
- StringBuffer,StringBuilder,ArrayList,Vector线程安全验证程序
- 线程安全和线程不安全理解
- 转:Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。
- 线程安全和线程不安全
- 什么是线程安全和线程不安全
- 什么是线程安全和线程不安全
- 线程安全和线程不安全理解
- 力所能及之java线程安全和非线程安全问题
- C#集合类(HashTable, Dictionary, ArrayList)与HashTable线程安全
- PHP非线程安全与线程安全版本的选择
- Java集合HashSet-ArrayList-HashMap的线程同步控制方法和区别
- 什么是线程安全和线程不安全
- Java 线程安全之volatile\StringBuffer\ArrayList\HashMap
- 手机短信验证码服务,为个人信息安全提供保障
- C# 4.0 之线程安全集合篇
- 线程安全和线程不安全理解
- C#的变迁史 - C# 4.0 之线程安全集合篇