400 028 6601

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

Java多线程理解:线程安全的集合对象-创新互联

1、概念介绍

你所需要的网站建设服务,我们均能行业靠前的水平为你提供.标准是产品质量的保证,主要从事做网站、网站建设、企业网站建设、手机网站开发、网页设计、成都品牌网站建设、网页制作、做网站、建网站。成都创新互联公司拥有实力坚强的技术研发团队及素养的视觉设计专才。

2、线程安全的集合对象

3、代码测试

public class Test {  public static void main(String [] args){      // 用来测试的List  
      List data = new ArrayList<>();      // 用来让主线程等待100个子线程执行完毕  
      CountDownLatch countDownLatch = new CountDownLatch(100);      // 启动100个子线程  
      for(int i=0;i<100;i++){
          SampleTask task = new SampleTask(data,countDownLatch);
          Thread thread = new Thread(task);
          thread.start();
      }      try{          // 主线程等待所有子线程执行完成,再向下执行  
          countDownLatch.await();
      }catch (InterruptedException e){  
          e.printStackTrace();  
      } 
      // List的size  
      System.out.println(data.size());
  }
}class SampleTask implements Runnable {
    CountDownLatch countDownLatch;
    List data;    public SampleTask(List data,CountDownLatch countDownLatch){        this.data = data;        this.countDownLatch = countDownLatch;
    }    @Override
    public void run() {        // 每个线程向List中添加100个元素  
        for(int i = 0; i < 100; i++)  
        {  
            data.add("1");
        }  
        // 完成一个子线程  
        countDownLatch.countDown();
    }
}

7次测试输出():

99981000010000ArrayIndexOutOfBoundsException1000099679936
public class Test {  public static void main(String [] args){      // 用来测试的List  
      List data = new Vector<>();      // 用来让主线程等待100个子线程执行完毕  
      CountDownLatch countDownLatch = new CountDownLatch(100);      // 启动100个子线程  
      for(int i=0;i<100;i++){
          SampleTask task = new SampleTask(data,countDownLatch);
          Thread thread = new Thread(task);
          thread.start();
      }      try{          // 主线程等待所有子线程执行完成,再向下执行  
          countDownLatch.await();
      }catch (InterruptedException e){  
          e.printStackTrace();  
      } 
      // List的size  
      System.out.println(data.size());
  }
}class SampleTask implements Runnable {
    CountDownLatch countDownLatch;
    List data;    public SampleTask(List data,CountDownLatch countDownLatch){        this.data = data;        this.countDownLatch = countDownLatch;
    }    @Override
    public void run() {        // 每个线程向List中添加100个元素  
        for(int i = 0; i < 100; i++)  
        {  
            data.add("1");
        }  
        // 完成一个子线程  
        countDownLatch.countDown();
    }
}

7次测试输出():

10000100001000010000100001000010000
public class Test {  public static void main(String [] args){      // 用来测试的List  
      List data = new ArrayList<>();      // 用来让主线程等待100个子线程执行完毕  
      CountDownLatch countDownLatch = new CountDownLatch(100);      // 启动100个子线程  
      for(int i=0;i<100;i++){
          SampleTask task = new SampleTask(data,countDownLatch);
          Thread thread = new Thread(task);
          thread.start();
      }      try{          // 主线程等待所有子线程执行完成,再向下执行  
          countDownLatch.await();
      }catch (InterruptedException e){  
          e.printStackTrace();  
      } 
      // List的size  
      System.out.println(data.size());
  }
}class SampleTask implements Runnable {
    CountDownLatch countDownLatch;
    List data;    public SampleTask(List data,CountDownLatch countDownLatch){        this.data = data;        this.countDownLatch = countDownLatch;
    }    @Override
    public void run() {        // 每个线程向List中添加100个元素  
        for(int i = 0; i < 100; i++)  
        {  
            synchronized(data){
                data.add("1");
            }
        }  
        // 完成一个子线程  
        countDownLatch.countDown();
    }
}

7次测试输出():

10000100001000010000100001000010000

3、原因分析

@Override public boolean add(E object) {
        Object[] a = array;        int s = size;        if (s == a.length) {
            Object[] newArray = new Object[s +
                    (s < (MIN_CAPACITY_INCREMENT / 2) ?
                     MIN_CAPACITY_INCREMENT : s >> 1)];
            System.arraycopy(a, 0, newArray, 0, s);
            array = a = newArray;
        }
        a[s] = object;
        size = s + 1;
        modCount++;        return true;
    }
@Override
    public synchronized boolean add(E object) {        if (elementCount == elementData.length) {
            growByOne();
        }
        elementData[elementCount++] = object;
        modCount++;        return true;
    }

4、线程安全的集合并不安全

分析以下场景:

synchronized(map){
Object value = map.get(key);if(value == null)
{
    value = new Object();
    map.put(key,value);
}return value;}

由于线程安全的集合对象是基于单个方法的同步,所以即使map是线程安全的,也会产生不同步现象。
在非单个方法的场景下,我们仍然需要使用synchronized加锁才能保证对象的同步。

代码测试:

public class Test {  public static void main(String [] args){      // 用来测试的List  
      List data = new Vector<>();      // 用来让主线程等待100个子线程执行完毕  
      CountDownLatch countDownLatch = new CountDownLatch(100);      // 启动100个子线程  
      for(int i=0;i<1000;i++){
          SampleTask task = new SampleTask(data,countDownLatch);
          Thread thread = new Thread(task);
          thread.start();
      }      try{          // 主线程等待所有子线程执行完成,再向下执行  
          countDownLatch.await();
      }catch (InterruptedException e){  
          e.printStackTrace();  
      } 
      // List的size  
      System.out.println(data.size());
  }
}class SampleTask implements Runnable {
    CountDownLatch countDownLatch;
    List data;    public SampleTask(List data,CountDownLatch countDownLatch){        this.data = data;        this.countDownLatch = countDownLatch;
    }    @Override
    public void run() {        // 每个线程向List中添加100个元素  
        int size = data.size();
        data.add(size,"1"); 
        // 完成一个子线程  
        countDownLatch.countDown();
    }
}
997
993
995
996
997
998
997

5、总结

创新互联www.cdcxhl.cn,专业提供香港、美国云服务器,动态BGP最优骨干路由自动选择,持续稳定高效的网络助力业务部署。公司持有工信部办法的idc、isp许可证, 机房独有T级流量清洗系统配攻击溯源,准确进行流量调度,确保服务器高可用性。佳节活动现已开启,新人活动云服务器买多久送多久。


网页名称:Java多线程理解:线程安全的集合对象-创新互联
分享网址:http://www.bluegullmedia.com/article/djpcpc.html

其他资讯

让你的专属顾问为你服务

0.0453s