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

来源:互联网 发布:mac版搜狗五笔造词 编辑:程序博客网 时间:2024/05/01 18:05

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

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

以下为测试代码:

package com.homeland.myapp;import java.util.Random;public class RandomSequence {public static void main(String[] args) {RandomGen d1 = new RandomGen(0, 10, 6);RandomGen d2 = new RandomGen(10, 20, 2);RandomGen d3 = new RandomGen(20, 30, 2);Thread t1 = new Thread(d1);Thread t2 = new Thread(d2);Thread t3 = new Thread(d3);t1.start();t2.start();t3.start();}}class RandomGen implements Runnable {Random r = new Random();int start, end, num;public RandomGen(int end) {this.end = end;}public RandomGen(int start, int end) {this.start = start;this.end = end;}public RandomGen(int start, int end, int num) {this.start = start;this.end = end;this.num = num;}@Overridepublic void run() {int c = 0;for (int i = 0; c < num; i++) {int a = r.nextInt(end);if (a >= start) {System.out.println("Number " + i + " is: " + a);c++;}}System.out.println("-----------------------");}}

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

以下为测试结果:

Number 0 is: 1Number 1 is: 5Number 2 is: 0Number 3 is: 7Number 4 is: 6Number 5 is: 8-----------------------Number 12 is: 26Number 13 is: 28-----------------------Number 0 is: 10Number 4 is: 11-----------------------

考虑到去掉重复的数字,代码作如下修改:

package com.homeland.myapp;import java.util.HashSet;import java.util.Random;import java.util.Set;public class RandomSequence {public static void main(String[] args) {RandomGen d1 = new RandomGen(0, 10, 6);RandomGen d2 = new RandomGen(10, 20, 2);RandomGen d3 = new RandomGen(20, 30, 2);Thread t1 = new Thread(d1);Thread t2 = new Thread(d2);Thread t3 = new Thread(d3);t1.start();t2.start();t3.start();}}class RandomGen implements Runnable {Random r = new Random();int start, end, num;public RandomGen(int end) {this.end = end;}public RandomGen(int start, int end) {this.start = start;this.end = end;}public RandomGen(int start, int end, int num) {this.start = start;this.end = end;this.num = num;}@Overridepublic void run() {Set<Integer> s = new HashSet<Integer>();for (int i = 0; s.size() < num; i++) {int a = r.nextInt(end);if (a >= start) {s.add(a);}}System.out.println("there are "+ num +" numbers in range: [" + start + ", " + end + "]:\n");System.out.println(s.toString());System.out.println("-----------------------");}}
其中一组结果如下:

there are 6 numbers in range: [0, 10]:[0, 2, 5, 6, 8, 9]-----------------------there are 2 numbers in range: [20, 30]:[22, 26]-----------------------there are 2 numbers in range: [10, 20]:[11, 13]-----------------------

我修改了代码,在某个位置上加入了syncronized关键字,还有用循环来控制线程的产生:

package com.homeland.myapp;import java.util.HashSet;import java.util.Random;import java.util.Set;public class RandomSequence {public static void main(String[] args) {int a[][] = {{0, 10, 6}, {10, 20, 2}, {20, 30, 4}, {30, 40, 3}, {40, 50, 5}, {50, 60, 7}, {60, 70, 8}, {70, 80, 9}, {80, 90, 4}, {90, 100, 7}};for (int i = 0; i < a.length; i++) {RandomGen d = new RandomGen(a[i][0], a[i][1], a[i][2]);Thread t = new Thread(d);t.start();}}}class RandomGen implements Runnable {Random r = new Random();int start, end, num;Set<Integer> s = new HashSet<Integer>();public RandomGen(int end) {this.end = end;}public RandomGen(int start, int end) {this.start = start;this.end = end;}public RandomGen(int start, int end, int num) {this.start = start;this.end = end;this.num = num;}@Overridepublic void run() {synchronized (s) {for (int i = 0; s.size() < num; i++) {int a = r.nextInt(end);if (a >= start) {s.add(a);}}System.out.println("there are "+ num +" numbers in range: [" + start + ", " + end + "]:\n");System.out.println(s.toString());System.out.println("-----------------------");}// sync}}
但是,我得到如下结果:

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

这个控制机制就是:

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


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

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

package com.homeland.myapp;import java.util.HashSet;import java.util.Random;import java.util.Set;public class RandomSequence {public static void main(String[] args) throws Exception {int a[][] = {{0, 10, 6}, {10, 20, 2}, {20, 30, 4}, {30, 40, 3}, {40, 50, 5}, {50, 60, 7}, {60, 70, 8}, {70, 80, 9}, {80, 90, 4}, {90, 100, 7}};for (int i = 0; i < a.length; i++) {RandomGen d = new RandomGen(a[i][0], a[i][1], a[i][2]);Thread t = new Thread(d);t.start();Thread.sleep(1);}}}class RandomGen implements Runnable {Random r = new Random();int start, end, num;private Set<Integer> s = new HashSet<Integer>();private static Object lock = new Object();public RandomGen(int end) {this.end = end;}public RandomGen(int start, int end) {this.start = start;this.end = end;}public RandomGen(int start, int end, int num) {this.start = start;this.end = end;this.num = num;}@Overridepublic void run() {synchronized (lock) {for (int i = 0; s.size() < num; i++) {int a = r.nextInt(end);if (a >= start) {s.add(a);}}System.out.println("there are "+ num +" numbers in range: [" + start + ", " + end + "]:\n");System.out.println(s.toString());System.out.println("-----------------------");}// sync}}
你木有看错!静态类成员被所有类实例共享。关键的一句:

private static Object lock = new Object();

当然,你也可以这么改:

package com.homeland.myapp;import java.util.HashSet;import java.util.Random;import java.util.Set;public class RandomSequence {public static void main(String[] args) throws Exception {int a[][] = {{0, 10, 6}, {10, 20, 2}, {20, 30, 4}, {30, 40, 3}, {40, 50, 5}, {50, 60, 7}, {60, 70, 8}, {70, 80, 9}, {80, 90, 4}, {90, 100, 7}};for (int i = 0; i < a.length; i++) {RandomGen d = new RandomGen(a[i][0], a[i][1], a[i][2]);Thread t = new Thread(d);t.start();Thread.sleep(1);}}}class RandomGen implements Runnable {static final Random r = new Random();static int start, end, num;private static Set<Integer> s = new HashSet<Integer>();public RandomGen(int end) {this.end = end;}public RandomGen(int start, int end) {this.start = start;this.end = end;}public RandomGen(int start, int end, int num) {this.start = start;this.end = end;this.num = num;}private static synchronized void printSequence() {for (int i = 0; s.size() < num; i++) {int a = r.nextInt(end);if (a >= start) {s.add(a);}}System.out.println("there are "+ num +" numbers in range: [" + start + ", " + end + "]:\n");System.out.println(s.toString());System.out.println("-----------------------");}@Overridepublic void run() {printSequence();}}

需要注意下,后面的静态方法会产生类似这样的结果:

there are 2 numbers in range: [10, 20]:[18, 3]-----------------------there are 4 numbers in range: [20, 30]:[18, 3, 20, 23]-----------------------there are 4 numbers in range: [20, 30]:[18, 3, 20, 23]-----------------------there are 3 numbers in range: [30, 40]:[18, 3, 20, 23]-----------------------there are 5 numbers in range: [40, 50]:[18, 3, 20, 23, 42]-----------------------there are 7 numbers in range: [50, 60]:[18, 3, 20, 23, 42, 58, 57]-----------------------there are 8 numbers in range: [60, 70]:[18, 3, 65, 20, 23, 42, 58, 57]-----------------------there are 9 numbers in range: [70, 80]:[18, 3, 65, 20, 23, 76, 42, 58, 57]-----------------------there are 4 numbers in range: [80, 90]:[18, 3, 65, 20, 23, 76, 42, 58, 57]-----------------------there are 7 numbers in range: [90, 100]:[18, 3, 65, 20, 23, 76, 42, 58, 57]-----------------------
所以,你需要这么修改代码:

package com.homeland.myapp;import java.util.HashSet;import java.util.Random;import java.util.Set;public class RandomSequence {public static void main(String[] args) throws Exception {int a[][] = {{0, 10, 6}, {10, 20, 2}, {20, 30, 4}, {30, 40, 3}, {40, 50, 5}, {50, 60, 7}, {60, 70, 8}, {70, 80, 9}, {80, 90, 4}, {90, 100, 7}};for (int i = 0; i < a.length; i++) {RandomGen d = new RandomGen(a[i][0], a[i][1], a[i][2]);Thread t = new Thread(d);t.start();Thread.sleep(1);}}}class RandomGen implements Runnable {static final Random r = new Random();int start, end, num;public RandomGen(int end) {this.end = end;}public RandomGen(int start, int end) {this.start = start;this.end = end;}public RandomGen(int start, int end, int num) {this.start = start;this.end = end;this.num = num;}private static synchronized void printSequence(int start, int end, int num) {final Set<Integer> s = new HashSet<Integer>();for (; s.size() < num;) {int a = r.nextInt(end);if (a >= start) {s.add(a);}}System.out.println("there are "+ num +" numbers in range: [" + start + ", " + end + "]:\n");System.out.println(s.toString());System.out.println("-----------------------");}@Overridepublic void run() {printSequence(start, end, num);}}
我得到的结果类似这种:

there are 6 numbers in range: [0, 10]:[0, 3, 4, 6, 7, 8]-----------------------there are 2 numbers in range: [10, 20]:[17, 13]-----------------------there are 4 numbers in range: [20, 30]:[20, 25, 26, 28]-----------------------there are 3 numbers in range: [30, 40]:[33, 38, 30]-----------------------there are 5 numbers in range: [40, 50]:[43, 40, 46, 47, 45]-----------------------there are 7 numbers in range: [50, 60]:[55, 54, 53, 59, 58, 57, 56]-----------------------there are 8 numbers in range: [60, 70]:[68, 69, 64, 66, 63, 62, 61, 60]-----------------------there are 9 numbers in range: [70, 80]:[70, 71, 76, 77, 78, 79, 72, 73, 74]-----------------------there are 4 numbers in range: [80, 90]:[86, 80, 82, 88]-----------------------there are 7 numbers in range: [90, 100]:[96, 97, 93, 92, 95, 94, 90]-----------------------

留个小尾巴:用HashSet去重效率如何呢?



原创粉丝点击