2015-05-31 24 views
5
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(); 
      } 
     } 
    } 

Tại sao nó in cùng một giá trị?Chuỗi Java tạo cùng một giá trị

Thread-0 gene data:-751128970 
Thread-1 gene data:-751128970 
+0

@ saka1029 có, nhưng nếu bạn tạo Random với hàm tạo mặc định, chúng sẽ không được tạo với cùng một hạt giống. –

Trả lời

1

Lớp Randompseudo-random number generator. Nó bắt đầu từ một số giá trị hạt giống. Nếu bạn không chỉ định hạt giống một cách rõ ràng, sẽ mất thời gian hiện tại làm hạt giống.

Nếu bạn nhanh chóng tạo hai đối tượng Random, chúng sẽ được tạo với cùng giá trị hạt giống và chúng sẽ tạo cùng một chuỗi các số ngẫu nhiên. - chỉnh sửa: K Erlandsson là đúng; điều này không thực sự đúng ...

Không tạo đối tượng Random mới mỗi lần bạn muốn tạo số ngẫu nhiên.

Chỉ có một biến tĩnh data, mà bạn đang sử dụng trong cả hai luồng. Cả hai sẽ viết và đọc từ cùng một biến.

phiên bản tốt hơn:

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

Lớp Ngẫu nhiên (ít nhất là trên JVM của tôi) không nhận được cùng một chuỗi ngay cả khi bạn tạo các đối tượng Ngẫu nhiên cùng một nansecod. Một cái gì đó như thế này: 'this (seedUniquifier()^System.nanoTime());' được thực hiện khi tạo một đối tượng Random trong đó seedUniquifier đảm bảo hai tạo ra hậu quả không mang lại cùng một hạt giống. –

1

Bạn đang chuyển nhượng giá trị ngẫu nhiên của bạn vào một lĩnh vực tĩnh. Bạn nên đặt biến dữ liệu thành biến cục bộ, tức là int data = new Random().nextInt();

Sử dụng phiên bản mới Random không thực sự là một vấn đề (mặc dù thiết kế xấu) vì hàm tạo mặc định chắc chắn sẽ sử dụng các hạt giống khác nhau.

Từ javadoc của hàm tạo mặc định.

Tạo trình tạo số ngẫu nhiên mới. Hàm khởi tạo này đặt hạt giống của trình tạo số ngẫu nhiên thành một giá trị rất có khả năng là khác biệt từ bất kỳ lời gọi nào khác của hàm tạo này.

2

Đó là vì chuỗi sẽ được thực thi thứ hai là đặt giá trị data trước khi chuỗi đầu tiên in bất kỳ thứ gì. Thực hiện một thay đổi nhỏ để mã của bạn minh họa điều này khá tốt:

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(); 
     } 
    } 
} 

Một thực hiện này đã cho tôi:

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

Như bạn có thể thấy, các giá trị được tạo ra là khác nhau (709.919.531 và 2022218312 trong này trường hợp), nhưng data đang được ghi đè bằng giá trị thứ hai trước khi giá trị đầu tiên được in. Điều này cho thấy nó không liên quan đến hạt giống của Random.

Một cách thứ hai để hiển thị này là để đồng bộ hóa trên lớp chính nó, mà (trong trường hợp này) sẽ chặn các chủ đề đó được thực hiện thứ hai cho đến khi là người đầu tiên đã hoàn tất thi công:

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(); 
     } 
    } 

} 

mà dẫn đến

Thread-0 shared: 1811879710 
Thread-1 shared: 1738616729 
0

Correcting @ giải pháp Jesper của, đối tượng ngẫu nhiên phải có cùng một đối tượng cho cả chủ đề theo thứ tự để làm việc như bạn mong đợi ...

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(); 
      } 
     } 
1

Đồng ý với Toby, nó không liên quan đến hạt giống. Nếu bạn loại bỏ các dữ liệu biến tĩnh chia sẻ, sau đó nó luôn luôn tạo ra số khác nhau

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: Chủ đề-0 gen dữ liệu: 1062913479 Chủ đề-1 gen dữ liệu: -599634908

Các vấn đề liên quan