Java:在指定的范围内生成指定数量的随机数

需求:我们需要在三个不同的数字段产生不同数量的随机数。

比如:[0, 10) 6个;[10, 20) 2个;[20, 30) 2个。

以下为测试代码:


 1 package com.homeland.myapp;
 2 
 3 import java.util.Random;
 4 
 5 
 6 public class RandomSequence {
 7 
 8     public static void main(String[] args) {
 9         RandomGen d1 = new RandomGen(0, 10, 6);
10         RandomGen d2 = new RandomGen(10, 20, 2);
11         RandomGen d3 = new RandomGen(20, 30, 2);
12         Thread t1 = new Thread(d1);
13         Thread t2 = new Thread(d2);
14         Thread t3 = new Thread(d3);
15         t1.start();
16         t2.start();
17         t3.start();
18     }
19 
20 }
21 
22 class RandomGen implements Runnable {
23     Random r = new Random();
24     int start, end, num;
25     
26     public RandomGen(int end) {
27         this.end = end;
28     }
29     
30     public RandomGen(int start, int end) {
31         this.start = start;
32         this.end = end;
33     }
34     
35     public RandomGen(int start, int end, int num) {
36         this.start = start;
37         this.end = end;
38         this.num = num;
39     }
40     
41     @Override
42     public void run() {
43         int c = 0;
44         for (int i = 0; c < num; i++) {
45             int a = r.nextInt(end);
46             if (a >= start) {
47                 System.out.println("Number " + i + " is: " + a);
48                 c++;
49             }
50         }
51         System.out.println("-----------------------");
52     }
53 }

以上三个不同的数字段都只包括第一个数字,不包括最后一个。也即,不包含上限。

以下为测试结果:


 1 Number 0 is: 1
 2 Number 1 is: 5
 3 Number 2 is: 0
 4 Number 3 is: 7
 5 Number 4 is: 6
 6 Number 5 is: 8
 7 -----------------------
 8 Number 12 is: 26
 9 Number 13 is: 28
10 -----------------------
11 Number 0 is: 10
12 Number 4 is: 11
13 -----------------------
考虑到去掉重复的数字,代码作如下修改:

 1 package com.homeland.myapp;
 2 
 3 import java.util.HashSet;
 4 import java.util.Random;
 5 import java.util.Set;
 6 
 7 
 8 public class RandomSequence {
 9 
10     public static void main(String[] args) {
11         RandomGen d1 = new RandomGen(0, 10, 6);
12         RandomGen d2 = new RandomGen(10, 20, 2);
13         RandomGen d3 = new RandomGen(20, 30, 2);
14         Thread t1 = new Thread(d1);
15         Thread t2 = new Thread(d2);
16         Thread t3 = new Thread(d3);
17         t1.start();
18         t2.start();
19         t3.start();
20     }
21 
22 }
23 
24 class RandomGen implements Runnable {
25     Random r = new Random();
26     int start, end, num;
27     
28     public RandomGen(int end) {
29         this.end = end;
30     }
31     
32     public RandomGen(int start, int end) {
33         this.start = start;
34         this.end = end;
35     }
36     
37     public RandomGen(int start, int end, int num) {
38         this.start = start;
39         this.end = end;
40         this.num = num;
41     }
42     
43     @Override
44     public void run() {
45         Set<Integer> s = new HashSet<Integer>();
46         for (int i = 0; s.size() < num; i++) {
47             int a = r.nextInt(end);
48             if (a >= start) {
49                 s.add(a);
50             }
51         }
52         System.out.println("there are "+ num +" numbers in range: [" + start + ", " + end + "]:\n");
53         System.out.println(s.toString());
54         System.out.println("-----------------------");
55     }
56 }
其中一组结果如下:

 1 there are 6 numbers in range: [0, 10]:
 2 
 3 [0, 2, 5, 6, 8, 9]
 4 -----------------------
 5 there are 2 numbers in range: [20, 30]:
 6 
 7 [22, 26]
 8 -----------------------
 9 there are 2 numbers in range: [10, 20]:
10 
11 [11, 13]
12 -----------------------
13 
我修改了代码,在某个位置上加入了syncronized关键字,还有用循环来控制线程的产生:

 1 package com.homeland.myapp;
 2 
 3 import java.util.HashSet;
 4 import java.util.Random;
 5 import java.util.Set;
 6 
 7 public class RandomSequence {
 8 
 9     public static void main(String[] args) {
10         
11         int a[][] = {
12                 {0, 10, 6}, {10, 20, 2}, {20, 30, 4}, 
13                 {30, 40, 3}, {40, 50, 5}, {50, 60, 7}, 
14                 {60, 70, 8}, {70, 80, 9}, {80, 90, 4}, {90, 100, 7}};
15         
16         for (int i = 0; i < a.length; i++) {
17             RandomGen d = new RandomGen(a[i][0], a[i][1], a[i][2]);
18             Thread t = new Thread(d);
19             t.start();
20         }
21     }
22 
23 }
24 
25 class RandomGen implements Runnable {
26     Random r = new Random();
27     int start, end, num;
28     Set<Integer> s = new HashSet<Integer>();
29     
30     public RandomGen(int end) {
31         this.end = end;
32     }
33     
34     public RandomGen(int start, int end) {
35         this.start = start;
36         this.end = end;
37     }
38     
39     public RandomGen(int start, int end, int num) {
40         this.start = start;
41         this.end = end;
42         this.num = num;
43     }
44     
45     @Override
46     public void run() {
47         synchronized (s) {
48             for (int i = 0; s.size() < num; i++) {
49                 int a = r.nextInt(end);
50                 if (a >= start) {
51                     s.add(a);
52                 }
53             }
54             System.out.println("there are "+ num +" numbers in range: [" + start + ", " + end + "]:\n");
55             System.out.println(s.toString());
56             System.out.println("-----------------------");
57         }// sync
58     }
59 }
但是,我得到如下结果:

 1 there are 4 numbers in range: [20, 30]:
 2 
 3 there are 3 numbers in range: [30, 40]:
 4 
 5 [35, 39, 30]
 6 -----------------------
 7 there are 6 numbers in range: [0, 10]:
 8 
 9 [0, 1, 2, 6, 7, 9]
10 -----------------------
11 there are 2 numbers in range: [10, 20]:
12 
13 [16, 12]
14 -----------------------
15 there are 7 numbers in range: [50, 60]:
16 
17 [51, 50, 55, 53, 52, 59, 58]
18 -----------------------
19 [21, 20, 24, 26]
20 -----------------------
21 there are 9 numbers in range: [70, 80]:
22 
23 [70, 71, 76, 77, 79, 72, 73, 74, 75]
24 -----------------------
25 there are 5 numbers in range: [40, 50]:
26 
27 [48, 43, 40, 46, 45]
28 -----------------------
29 there are 7 numbers in range: [90, 100]:
30 
31 [98, 99, 96, 93, 95, 94, 90]
32 -----------------------
33 there are 8 numbers in range: [60, 70]:
34 
35 [68, 69, 64, 65, 66, 67, 62, 60]
36 -----------------------
37 there are 4 numbers in range: [80, 90]:
38 
39 [84, 87, 83, 89]
40 -----------------------
看起来某些部分的输出时交错的。看来我需要另外一种控制机制。

这个控制机制就是:


1 Thread.sleep(5000);
把这句放到上面代码中的main()方法的循环中去。

上面的Thread.sleep(5000)不是没有问题的。你可以试想一下,如果数字的范围很大呢?

所以,问题的关键是:如何保证线程同步或者说线程对共享资源的互斥访问呢?把代码做如下修改:


 1 package com.homeland.myapp;
 2 
 3 import java.util.HashSet;
 4 import java.util.Random;
 5 import java.util.Set;
 6 
 7 public class RandomSequence {
 8 
 9     public static void main(String[] args) throws Exception {
10         
11         int a[][] = {
12                 {0, 10, 6}, {10, 20, 2}, {20, 30, 4}, 
13                 {30, 40, 3}, {40, 50, 5}, {50, 60, 7}, 
14                 {60, 70, 8}, {70, 80, 9}, {80, 90, 4}, {90, 100, 7}};
15         
16         for (int i = 0; i < a.length; i++) {
17             RandomGen d = new RandomGen(a[i][0], a[i][1], a[i][2]);
18             Thread t = new Thread(d);
19             t.start();
20             Thread.sleep(1);
21         }
22     }
23 
24 }
25 
26 class RandomGen implements Runnable {
27     Random r = new Random();
28     int start, end, num;
29     private Set<Integer> s = new HashSet<Integer>();
30     private static Object lock = new Object();
31     
32     public RandomGen(int end) {
33         this.end = end;
34     }
35     
36     public RandomGen(int start, int end) {
37         this.start = start;
38         this.end = end;
39     }
40     
41     public RandomGen(int start, int end, int num) {
42         this.start = start;
43         this.end = end;
44         this.num = num;
45     }
46     
47     
48     @Override
49     public void run() {
50         synchronized (lock) {
51             for (int i = 0; s.size() < num; i++) {
52                 int a = r.nextInt(end);
53                 if (a >= start) {
54                     s.add(a);
55                 }
56             }
57             System.out.println("there are "+ num +" numbers in range: [" + start + ", " + end + "]:\n");
58             System.out.println(s.toString());
59             System.out.println("-----------------------");
60         }// sync
61     }
62 }
你木有看错!静态类成员被所有类实例共享。关键的一句:

1 private static Object lock = new Object();
当然,你也可以这么改:

 1 package com.homeland.myapp;
 2 
 3 import java.util.HashSet;
 4 import java.util.Random;
 5 import java.util.Set;
 6 
 7 public class RandomSequence {
 8 
 9     public static void main(String[] args) throws Exception {
10         
11         int a[][] = {
12                 {0, 10, 6}, {10, 20, 2}, {20, 30, 4}, 
13                 {30, 40, 3}, {40, 50, 5}, {50, 60, 7}, 
14                 {60, 70, 8}, {70, 80, 9}, {80, 90, 4}, {90, 100, 7}};
15         
16         for (int i = 0; i < a.length; i++) {
17             RandomGen d = new RandomGen(a[i][0], a[i][1], a[i][2]);
18             Thread t = new Thread(d);
19             t.start();
20             Thread.sleep(1);
21         }
22     }
23 
24 }
25 
26 class RandomGen implements Runnable {
27     static final Random r = new Random();
28     static int start, end, num;
29     private static Set<Integer> s = new HashSet<Integer>();
30     
31     public RandomGen(int end) {
32         this.end = end;
33     }
34     
35     public RandomGen(int start, int end) {
36         this.start = start;
37         this.end = end;
38     }
39     
40     public RandomGen(int start, int end, int num) {
41         this.start = start;
42         this.end = end;
43         this.num = num;
44     }
45     
46     private static synchronized void printSequence() {
47         for (int i = 0; s.size() < num; i++) {
48             int a = r.nextInt(end);
49             if (a >= start) {
50                 s.add(a);
51             }
52         }
53         System.out.println("there are "+ num +" numbers in range: [" + start + ", " + end + "]:\n");
54         System.out.println(s.toString());
55         System.out.println("-----------------------");
56     }
57     
58     @Override
59     public void run() {
60         printSequence();
61     }
62 }
需要注意下,后面的静态方法会产生类似这样的结果:

 1 there are 2 numbers in range: [10, 20]:
 2 
 3 [18, 3]
 4 -----------------------
 5 there are 4 numbers in range: [20, 30]:
 6 
 7 [18, 3, 20, 23]
 8 -----------------------
 9 there are 4 numbers in range: [20, 30]:
10 
11 [18, 3, 20, 23]
12 -----------------------
13 there are 3 numbers in range: [30, 40]:
14 
15 [18, 3, 20, 23]
16 -----------------------
17 there are 5 numbers in range: [40, 50]:
18 
19 [18, 3, 20, 23, 42]
20 -----------------------
21 there are 7 numbers in range: [50, 60]:
22 
23 [18, 3, 20, 23, 42, 58, 57]
24 -----------------------
25 there are 8 numbers in range: [60, 70]:
26 
27 [18, 3, 65, 20, 23, 42, 58, 57]
28 -----------------------
29 there are 9 numbers in range: [70, 80]:
30 
31 [18, 3, 65, 20, 23, 76, 42, 58, 57]
32 -----------------------
33 there are 4 numbers in range: [80, 90]:
34 
35 [18, 3, 65, 20, 23, 76, 42, 58, 57]
36 -----------------------
37 there are 7 numbers in range: [90, 100]:
38 
39 [18, 3, 65, 20, 23, 76, 42, 58, 57]
40 -----------------------
41 
所以,你需要这么修改代码:

 1 package com.homeland.myapp;
 2 
 3 import java.util.HashSet;
 4 import java.util.Random;
 5 import java.util.Set;
 6 
 7 public class RandomSequence {
 8 
 9     public static void main(String[] args) throws Exception {
10         
11         int a[][] = {
12                 {0, 10, 6}, {10, 20, 2}, {20, 30, 4}, 
13                 {30, 40, 3}, {40, 50, 5}, {50, 60, 7}, 
14                 {60, 70, 8}, {70, 80, 9}, {80, 90, 4}, {90, 100, 7}};
15         
16         for (int i = 0; i < a.length; i++) {
17             RandomGen d = new RandomGen(a[i][0], a[i][1], a[i][2]);
18             Thread t = new Thread(d);
19             t.start();
20             Thread.sleep(1);
21         }
22     }
23 
24 }
25 
26 class RandomGen implements Runnable {
27     static final Random r = new Random();
28     int start, end, num;
29     
30     public RandomGen(int end) {
31         this.end = end;
32     }
33     
34     public RandomGen(int start, int end) {
35         this.start = start;
36         this.end = end;
37     }
38     
39     public RandomGen(int start, int end, int num) {
40         this.start = start;
41         this.end = end;
42         this.num = num;
43     }
44     
45     private static synchronized void printSequence(int start, int end, int num) {
46         final Set<Integer> s = new HashSet<Integer>();
47         for (; s.size() < num;) {
48             int a = r.nextInt(end);
49             if (a >= start) {
50                 s.add(a);
51             }
52         }
53         System.out.println("there are "+ num +" numbers in range: [" + start + ", " + end + "]:\n");
54         System.out.println(s.toString());
55         System.out.println("-----------------------");
56     }
57     
58     @Override
59     public void run() {
60         printSequence(start, end, num);
61     }
62 }
我得到的结果类似这种:

 1 there are 6 numbers in range: [0, 10]:
 2 
 3 [0, 3, 4, 6, 7, 8]
 4 -----------------------
 5 there are 2 numbers in range: [10, 20]:
 6 
 7 [17, 13]
 8 -----------------------
 9 there are 4 numbers in range: [20, 30]:
10 
11 [20, 25, 26, 28]
12 -----------------------
13 there are 3 numbers in range: [30, 40]:
14 
15 [33, 38, 30]
16 -----------------------
17 there are 5 numbers in range: [40, 50]:
18 
19 [43, 40, 46, 47, 45]
20 -----------------------
21 there are 7 numbers in range: [50, 60]:
22 
23 [55, 54, 53, 59, 58, 57, 56]
24 -----------------------
25 there are 8 numbers in range: [60, 70]:
26 
27 [68, 69, 64, 66, 63, 62, 61, 60]
28 -----------------------
29 there are 9 numbers in range: [70, 80]:
30 
31 [70, 71, 76, 77, 78, 79, 72, 73, 74]
32 -----------------------
33 there are 4 numbers in range: [80, 90]:
34 
35 [86, 80, 82, 88]
36 -----------------------
37 there are 7 numbers in range: [90, 100]:
38 
39 [96, 97, 93, 92, 95, 94, 90]
40 -----------------------
41 
留个小尾巴:用HashSet去重效率如何呢?

posted on 2014-05-15 16:05 马克思.佩恩 阅读(229) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 
<2014年5月>
日一二三四五六
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

导航

统计

留言簿

随笔档案

文章分类

相册

搜索

最新评论