ArrayList,Vector线程安全性测试

时间:2021-01-25 18:16:54
  1. import java.util.ArrayList;
  2. import java.util.List;
  3. //实现Runnable接口的线程
  4. public class HelloThread implements Runnable {
  5. String name;
  6. List<String> v;
  7. HelloThread(String name, List<String> v) {
  8. this.name = name;
  9. this.v = v;
  10. }
  11. public void run() {
  12. System.out.println(name + "start");
  13. while(true) {
  14. v.add(name + ".add");
  15. System.out.println(name + " list size is " + v.size());
  16. try {
  17. Thread.sleep(10);
  18. } catch(InterruptedException e) {
  19. System.out.println(e.getMessage());
  20. }
  21. }
  22. }
  23. public static void main(String args[]) throws InterruptedException {
  24. List<String> v = new ArrayList<String>();
  25. HelloThread hello1 = new HelloThread("hello1", v);
  26. HelloThread hello2 = new HelloThread("hello2", v);
  27. HelloThread hello3 = new HelloThread("hello3", v);
  28. Thread h1 = new Thread(hello1);
  29. Thread h2 = new Thread(hello2);
  30. Thread h3 = new Thread(hello3);
  31. h1.start();
  32. h2.start();
  33. h3.start();
  34. }
  35. }

结果:

hello3start
hello3 list size is 1
hello1start
hello1 list size is 2
hello2start
hello2 list size is 3
hello3 list size is 4 
hello1 list size is 5
hello2 list size is 4 
hello3 list size is 6
hello1 list size is 8
hello2 list size is 7
hello1 list size is 9 
hello3 list size is 10
hello2 list size is 9

加了12次,但size却只有10,不安全

改成号称线程安全的Vector:

  1. import java.util.Vector;
  2. //实现Runnable接口的线程
  3. public class HelloThread implements Runnable {
  4. String name;
  5. Vector<String> v;
  6. HelloThread(String name, Vector<String> v) {
  7. this.name = name;
  8. this.v = v;
  9. }
  10. public void run() {
  11. System.out.println(name + "start");
  12. while(true) {
  13. v.add(name + ".add");
  14. System.out.println(name + " vector size is " + v.size());
  15. try {
  16. Thread.sleep(10);
  17. } catch(InterruptedException e) {
  18. System.out.println(e.getMessage());
  19. }
  20. }
  21. }
  22. public static void main(String args[]) throws InterruptedException {
  23. Vector<String> v = new Vector<String>();
  24. HelloThread hello1 = new HelloThread("hello1", v);
  25. HelloThread hello2 = new HelloThread("hello2", v);
  26. HelloThread hello3 = new HelloThread("hello3", v);
  27. Thread h1 = new Thread(hello1);
  28. Thread h2 = new Thread(hello2);
  29. Thread h3 = new Thread(hello3);
  30. h1.start();
  31. h2.start();
  32. h3.start();
  33. }
  34. }

结果:

hello1start
hello1 vector size is 1
hello2start
hello2 vector size is 2
hello3start
hello3 vector size is 3
hello1 vector size is 4
hello2 vector size is 5
hello3 vector size is 6
hello1 vector size is 7
hello2 vector size is 8
hello3 vector size is 9
hello1 vector size is 10
hello2 vector size is 11
hello3 vector size is 12
hello1 vector size is 13
hello3 vector size is 15
hello2 vector size is 15 
hello1 vector size is 16

也出现了线程不安全现象吗?不是的

这个不算线程不安全,加了16次,size是16,恰恰是线程安全的表现,只不过是待两个线程都add完了之后才调的size(),所以都是15,跳过了14。

以上一样的程序多试几次就出现了,另外关于Vector的thread-safety

All Vector methods are synchronized themselves, so as long as you are only synchronizing around a single method, your own synchronization is not necessary. If you have several method calls, which depend on each other, e.g. something like vec.get(vec.size()-2) to get the second last element, you have to use your own synchronization since otherwise, the vector may change between vec.size() and vec.get().

所有的Vector的方法对它们自己而言都是 synchronized的,所以如果只要同步单个方法,自己额外添加的同步措施就失去必要了。如果有几个方法需要调用,且它们互相存在依赖,比如 vec.get(vec.size()-2),是要得到倒数第二个元素,那么就必须加上自己的同步措施,因为否则的话,vector有可能在 vec.size() 和 vec.get() 之间发生改变