验证ArrayList线程不安全,redisson提供的分布式集合线程安全

借鉴这篇文章的测试方法。

一。.测试ArrayList

public 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) + "  ");  
            //输出结果是乱的,因为不一定哪个线程先把线程名放进集合
        }  
    } 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值