【Java线程安全和非线程安全】

ArrayList和Vector有什么区别?HashMap和HashTable有什么区别?StringBuilder和StringBuffer有什么区别?这些都是Java面试中常见的基础问题。面对这样的问题,回答是:ArrayList是非线程安全的,Vector是线程安全的;HashMap是非线程安全的,HashTable是线程安全的;StringBuilder是非线程安全的,StringBuffer是线程安全的。因为这是昨晚刚背的《Java面试题大全》上面写的。此时如果继续问:什么是线程安全?线程安全和非线程安全有什么区别?分别在什么情况下使用?这样一连串的问题,一口老血就电脑桌面壁纸喷出来了…

  非线程安全的现象模拟

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

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

  [java]

  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();

  }

  }

  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异常。(如果没有这个现象可以多试几次)

posted on 2013-09-12 15:50  潇洒kman  阅读(212)  评论(0编辑  收藏  举报