zoukankan      html  css  js  c++  java
  • ArrayList的线程安全测试

    public class TestThread implements Runnable{  
      
        private List list;  
        CountDownLatch cdl;  
          
          
        public TestThread(List list,CountDownLatch cdl){  
            this.list=list;  
            this.cdl=cdl;  
        }  
        /** 
         * @see java.lang.Runnable#run() 
         */  
        @Override  
        public void run() {  
            for(int i=0;i<500;i++){  
                list.add("a");  
            }     
            try {  
                cdl.countDown();  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
          
        public static void main(String[] args) throws Exception{  
            int count=32;  
            CountDownLatch cdl=new CountDownLatch(count);  
            List list=new ArrayList();  
            //List list=Collections.synchronizedList(new ArrayList());  
            TestThread t1=new TestThread(list,cdl);  
            for(int i=0;i<count;i++){  
                new Thread(t1).start();  
            }         
            cdl.await();  
            System.out.println("size:"+list.size());  
        }  
      
    }
    复制代码

    结论是,用ArrayList时,出现如下错误:

    Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 452  
        at java.util.ArrayList.add(ArrayList.java:352)  

    改为List list=Collections.synchronizedList(new ArrayList())之后,就正常了。

    List<Map<String,Object>> data=new ArrayList<Map<String,Object>>();

            那么为了解决这个线程安全问题你可以这么使用Collections.synchronizedList(),如:

            List<Map<String,Object>> data=Collections.synchronizedList(new ArrayList<Map<String,Object>>());

           其他的都没变,使用的方法也几乎与ArrayList一样,大家可以参考下api文档;

    额外说下 ArrayList与LinkedList;这两个都是接口List下的一个实现,用法都一样,但用的场所的有点不同,ArrayList适合于进行大量 的随机访问的情况下使用,LinkedList适合在表中进行插入、删除时使用,二者都是非线程安全,解决方法同上(为了避免线程安全,以上采取的方法, 特别是第二种,其实是非常损耗性能的)。

    线程安全和非线程安全  

    ArrayList和Vector有什么区 别?HashMap和HashTable有什么区别?StringBuilder和StringBuffer有什么区别?这些都是Java面试中常见的基 础问题。面对这样的问题,回答是:ArrayList是非线程安全的,Vector是线程安全的;HashMap是非线程安全的,HashTable是线 程安全的;StringBuilder是非线程安全的,StringBuffer是线程安全的。因为这是

    昨晚刚背的《Java面试题大全》上面写的。此时如果继续问:什么是线程安全?线程安全和非线程安全有什么区别?分别在什么情况下使用?这样一连串的问题,一口老血就喷出来了

     

    非线程安全的现象模拟

     

    这里就使用ArrayList和Vector二者来说明。 

    下面的代码,在主线程中new了一个非线程安全的ArrayList,然后开1000个线程分别向这个ArrayList里面添加元素,每个线程添加100个元素,等所有线程执行完成后,这个ArrayList

    的size应该是多少?应该是100000个?

    复制代码
    public class Main  {
           public static void main(String[] args)      {
               // 进行 10次测试  
             for(int i = 0; i < 10; i++) 
             {
                   test();
              }
          }
                 public static void test()      {
              // 用来测试的List     
         List<Object> list = new ArrayList<Object>();   
                      // 线程数量(1000)   
           int threadCount = 1000;    
                     // 用来让主线程等待threadCount个子线程执行完毕     
         CountDownLatch countDownLatch = new CountDownLatch(threadCount); 
                       // 启动threadCount个子线程        
      for(int i = 0; i < threadCount; i++)
          {               
    Thread thread = new Thread(new MyThread(list,countDownLatch));
                   thread.start(); 
             }    
                      try        {  
                 // 主线程等待所有子线程执行完成,再向下执行     
             countDownLatch.await();   
           } 
              catch (InterruptedException e)          { 
                  e.printStackTrace();     
         }                      
    // List 的size 
             System.out.println(list.size()); 
         }
      }
         class MyThread implements Runnable  {      
    private List<Object> list;
                 private CountDownLatch countDownLatch;    
             public MyThread(List<Object> list, CountDownLatch countDownLatch)      { 
             this.list = list; 
             this.countDownLatch = countDownLatch;   
       }   
              public void run()      { 
             // 每个线程向List中添加100个元素      
        for(int i = 0; i < 100; i++)       
       { 
                 list.add(new Object());    
          }    
                     // 完成一个子线程        
      countDownLatch.countDown();
     }
    }
    复制代码

    上面进行了10次测试(为什么要测试10次?因为非线程安全并不是每次都会导致问题)。 

    输出结果: 

    99946 

    100000 

    100000 

    100000 

    99998 

    99959 

    100000 

    99975 

    100000 

    99996 

    上面的输出结果发现,并不是每次测试结果都是100000,有好几次测试最后ArrayList的size小于100000,甚至时不时会抛出个IndexOutOfBoundsException异常。

    (如果没有这个现象可以多试几次) 

    这就是非线程安全带来的问题了。上面的代码如果用于生产环境,就会有隐患就会有BUG了。 

    再用线程安全的Vector来进行测试,上面代码改变一处,test()方法中

     1 List<Object> list = new ArrayList<Object>(); 

    改成

    1 List<Object> list = new Vector<Object>(); 

    再运行程序。 

    输出结果: 

    100000 

    100000

  • 相关阅读:
    14.18 InnoDB Backup and Recovery 备份和恢复:
    14.18 InnoDB Backup and Recovery 备份和恢复:
    php使用 _before_index() 来实现访问页面前,判断登录
    php使用 _before_index() 来实现访问页面前,判断登录
    查询方式实例演示
    查询方式实例演示
    haproxy timeout server 46000 后台超时时间
    haproxy timeout server 46000 后台超时时间
    14.10.5 Reclaiming Disk Space with TRUNCATE TABLE 回收空间使用TRUNCATE TABLE
    14.10.5 Reclaiming Disk Space with TRUNCATE TABLE 回收空间使用TRUNCATE TABLE
  • 原文地址:https://www.cnblogs.com/Berryxiong/p/6180553.html
Copyright © 2011-2022 走看看