Java thread generates a single value

public class ThinkThreadLocal { public static int data; public static void main(String[] args) { for(int i = 0; i < 2; i++) { new Thread(new Runnable(){ @Override public void run() { data = new Random().nextInt(); System.out.println(Thread.currentThread().getName() + " gene data:" + data); } }).start(); } } } 

Why does it print the same value?

 Thread-0 gene data:-751128970 Thread-1 gene data:-751128970 
+5
source share
5 answers

This is because the thread that will be executed by the second sets the data value before the first thread prints anything. Doing a slight modification to your code illustrates this pretty well:

 public final class ThinkThreadLocal { public static int data; public static void main(String[] args) { for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { int temp = data = new Random().nextInt(); System.out.println(Thread.currentThread().getName() + " temp: " + temp); System.out.println(Thread.currentThread().getName() + " shared: " + data); } }).start(); } } } 

One execution of this gave me:

 Thread-0 temp: 709919531 Thread-1 temp: 2022218312 Thread-0 shared: 2022218312 Thread-1 shared: 2022218312 

As you can see, the generated values ​​are different (709919531 and 2022218312 in this case), but data overwritten by the second value before the first value is printed. This shows that it is not related to the Random seed.

The second way to show this is to synchronize with the class itself, which (in this case) blocks the thread that is executed by the second, until the first completes execution:

 public final class ThinkThreadLocal { public static int data; public static void main(String[] args) { for (int i = 0; i < 2; i++) { new Thread(new Runnable() { @Override public void run() { synchronized (ThinkThreadLocal.class) { data = new Random().nextInt(); System.out.println(Thread.currentThread().getName() + " shared: " + data); } } }).start(); } } } 

as a result

 Thread-0 shared: 1811879710 Thread-1 shared: 1738616729 
+2
source

The Random class is a pseudo-random number generator . It starts with some initial value. Unless you specify a seed explicitly, it will take the current time as a seed.

If you quickly create two Random objects, they will be created with the same initial value, and they will generate the same sequence of random numbers. - change: K Erlandsson is right; it is not true...

Do not create a new Random object every time you want to create a random number.

There is only one static data variable that you use in both threads. They will write and read from the same variable.

The best version:

 public static void main(String[] args) { for(int i = 0; i < 2; i++) { new Thread(new Runnable(){ private final Random random = new Random(); @Override public void run() { int data = random.nextInt(); System.out.println(Thread.currentThread().getName() + " gene data:" + data); } }).start(); } } 
+1
source

You assign your random value to a static field. You must make the data variable a local variable, i.e. int data = new Random().nextInt();

Using new instances of Random is actually not a problem (although this is a poor design), since the default constructor makes it pretty confident to use different seeds.

From javadoc default constructor.

Creates a new random number generator. This constructor sets the seed of a random number generator to a value that is likely to be different from any other call to this constructor.

+1
source

Agree with Toby, he is not related to the seed. If you delete the general data of a static variable, then it always generates a different number

 public class ThinkThreadLocal { public static void main(String[] args) { for(int i = 0; i < 2; i++) { new Thread(new Runnable(){ @Override public void run() { System.out.println(Thread.currentThread().getName() + " gene data:" + new Random().nextInt()); } }).start(); } } } 

Output: Thread-0 gene data: 1062913479 Thread-1 gene data: -599634908

+1
source

Adjusting the @Jesper solution, the random object must be the same object for both threads in order to work as you expect ...

 public class ThinkThreadLocal { public static int data; public static void main(String[] args) { final Random random = new Random(); for(int i = 0; i < 2; i++) { new Thread(new Runnable(){ @Override public void run() { data = random.nextInt(); System.out.println(Thread.currentThread().getName() + " gene data:" + data); } }).start(); } } 
0
source

All Articles