需求:我们需要在三个不同的数字段产生不同数量的随机数。
比如:[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;
}
@Override
public 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: 1
Number 1 is: 5
Number 2 is: 0
Number 3 is: 7
Number 4 is: 6
Number 5 is: 8
-----------------------
Number 12 is: 26
Number 13 is: 28
-----------------------
Number 0 is: 10
Number 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;
}
@Override
public 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;
}
@Override
public 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;
}
@Override
public 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("-----------------------");
}
@Override
public 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("-----------------------");
}
@Override
public 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去重效率如何呢?