场景: 应用中有一个IPList数组,用于屏蔽一些IP的访问,这个IP数组可以动态修改(写入)。
我之前设计是这样:
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
 | 
private String[] ipList;public boolean isDisallowIP(String ip){    if (ipList == null)    {        return true;    }    else    {        for (String theIP: ipList) {            if (ip.startsWith(theIP)) {                return true;            }        }        return false;    }} | 
//更新IP列表
public void updateIPList()
{
String[] tempList = new String[...];
......
ipList = tempList;
}
今天我在想,如果我刚刚添加一个新的IP到IPList中或从IPList数组中删除几个元素,而这个时候有多个线程同时在读取IPList会不会造成索引越界?
我特意写了一段代码测试:
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
70 
71 
72 
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
 | 
package test;public class ThreadTest{         private int list[];         public ThreadTest()    {        list = new int[1024];                 for(int i=0;i<1024;i++)        {            list[i] = (int)(Math.random() * 10000);        }                 for(int i=0;i<10;i++)        {            new Read().start();        }                 for(int i=0;i<1;i++)        {            new Update().start();        }    }         //多个读    class Read extends Thread    {        public void run()        {            while(true)            {                //for(int x : list) 生成的字节码反编译出来是竟是这样: (真是有点侥幸...)  不会抛出索引越界                /*                int ai[];                int j = (ai = list).length;                for(int i = 0; i < j; i++)                {                    int x = ai[i];                    System.out.println(x);                }                */                for(int x : list)                {                    System.out.println(x);                }                                                  /*                //int[] list = ThreadTest.this.list; //如果不加这行,下面就会抛出索引越界                                 int size = list.length;                for(int i=0;i<size;i++)                {                    //int x = list[i];                                         System.out.println(list[i]);                }                */            }                  }    }         //单个修改    class Update extends Thread    {        public void run()        {            while(true)            {                int count = (int)(Math.random() * 1024);                int[] temp = new int[count];                                 for(int i=0;i<count;i++)                {                    temp[i] = (int)(Math.random() * 10000);                }                                 list = temp;            }        }    }              public static void main(String[] args)    {        new ThreadTest();    }} | 
| 
 经过这段代码测试结果表明:单线程修改IPList,多线程读取IPList的时候,在读取的代码段,最好这样操作: String tempList = ipList; //其实想象在c语言中的指针,就非常好理解了。 int count = tempList.length; for(int i=0;i<count;i++) { ... } 这样就不会出现当动态修改数组时,出现访问时索引越界。  | 
2013-08-06
原文:http://www.cnblogs.com/personnel/p/4584905.html