Java多线程理解:线程安全的集合对象

发布时间:2020-07-22 15:54:16 作者:沙漏半杯
来源:网络 阅读:287

1、概念介绍

2、线程安全的集合对象

3、代码测试

public class Test {  public static void main(String [] args){      // 用来测试的List  
      List<String> 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<String> data;    public SampleTask(List<String> 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<String> 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<String> data;    public SampleTask(List<String> 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<String> 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<String> data;    public SampleTask(List<String> 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<String> 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<String> data;    public SampleTask(List<String> 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、总结


推荐阅读:
  1. java集合中的线程安全
  2. 怎么理解java中的集合

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java 多线程 线程安全

上一篇:软件开发防泄密解决方案,需重视的几点

下一篇:js如何实现捕获与冒泡机制

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》