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

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去重效率如何呢?

你可能感兴趣的:(Java:在指定的范围内生成指定数量的随机数)