2012-03-05 14 views
16

Có phải lập trình kém để khởi tạo hai luồng với cùng một thể hiện của runnable không? Sự khác biệt nào khi khởi tạo với các trường hợp riêng biệt của một runnable, và không chia sẻ các vị trí bộ nhớ ở tất cả cho cùng một thể hiện của một runnable có liên quan gì đến hiệu năng không?Khởi tạo hai luồng với cùng một thể hiện của runnable

public static void main(String[] args)throws Exception { 
    H h = new H(); 
    H h2 = new H(); 
    Thread j = new Thread(h); 
    j.setName("11"); 

    Thread jj = new Thread(h);//instead of new H() 
    jj.setName("22"); 
    j.start(); 
    jj.start(); 
} 

class H implements Runnable { 
    public void run() { 
     while(true) { 
      System.out.println(Thread.currentThread().getName()); 
     } 
    } 
} 

Trả lời

17

Thật tuyệt khi làm điều đó miễn là mã bạn đang chạy được thiết kế để hỗ trợ điều đó. Không chỉ nó sẽ tiết kiệm một số bộ nhớ bằng cách có một trường hợp duy nhất thay vì nhiều trường hợp, nhưng nếu những chủ đề là cố gắng để giao tiếp thông qua dữ liệu được chia sẻ, sau đó nó có thể được hoàn toàn yêu cầu! Phải được thực hiện một cách cẩn thận, nhưng từ quan điểm của hệ thống luồng chính nó, hoàn toàn không có vấn đề gì trong việc có hai chủ đề gọi phương thức run của một duy nhất Runnable bản sao.

8

H không có bất kỳ trạng thái cá thể nào, sử dụng nhiều phiên bản sẽ không thành vấn đề. Bạn cần phải cẩn thận khi các trường hợp bắt đầu lưu trữ trạng thái Runnable.

public class Main implements Runnable { 
    volatile int i; 
     public void run() { 
     for (i = 0; i < 100; i++) { 
      System.out.println(i); 
     } 
    } 

    public static void main(String[] args) { 
     Main a = new Main(); 
     Thread t1 = new Thread(a); 
     Thread t2 = new Thread(a); 
     t1.start(); 
     t2.start(); 
    }   
} 

Điều gì nhận được printed? Khi bạn cần chia sẻ trạng thái giữa các luồng, bạn nên sử dụng các lớp trong java.util.concurrent. Chúng được viết chủ yếu bởi một chuyên gia về đa luồng (Doug Lea, tác giả của Concurrent Programming in Java) và được nhiều người thử nghiệm. Tiết kiệm cho mình một số đau khổ. :)

+0

woo, tất cả đều bị hỏng. rất thú vị –

7

Có phải lập trình kém để khởi tạo hai luồng có cùng phiên bản của runnable không?

Không cụ thể. Tuy nhiên, nếu cá thể Runnable có trường mẫu, thì bạn sẽ cần đảm bảo rằng tất cả quyền truy cập vào các trường theo luồng được đồng bộ hóa đúng cách và điều này sẽ làm cho mã phức tạp hơn.

Điều gì sẽ khác biệt khi khởi tạo với các phiên bản chạy riêng biệt và chia sẻ vị trí bộ nhớ cho cùng một trường hợp có thể chạy với hiệu suất?

Bộ nhớ được lưu bằng cách chia sẻ Runnable thể hiện giữa nhiều chủ đề là không đáng kể ... trừ khi Runnable giữ một lượng dữ liệu ví dụ đáng kể. (Và nếu có, nhiều khả năng rằng điều này sẽ làm cho các trường hợp không thể chia sẻ.)


lớp H của bạn là một ví dụ trong đó trường hợp chia sẻ là an toàn, nhưng vô nghĩa kể từ khi tiết kiệm bộ nhớ là không đáng kể. (Một đối tượng Runnable không có trường mẫu nào chiếm khoảng 8 đến 16 byte, tùy thuộc vào nền tảng.)

0

Để hiểu dễ dàng (dựa trên nhận xét của Stephen), thêm khối chương trình bên dưới về tác động của việc truy cập cá thể biến từ một khối không đồng bộ với cùng một thể hiện của Runnable hiển thị các kết quả bất ngờ.

public class SynchronizedInstanceMethod implements Runnable{ 

private int counter; 

public SynchronizedInstanceMethod(int counterValue){ 
    this.counter = counterValue; 
} 

private synchronized void displayMessage(){ 
    System.out.println(" Display Message "); 
} 

private void modifyCounter(){ 
    this.counter++; 
    System.out.println("Value -- "+ this.counter); 
} 

@Override 
public void run() { 
    this.displayMessage(); 
    this.modifyCounter(); 
} 

public static void main(String[] args) { 
    SynchronizedInstanceMethod instance = new SynchronizedInstanceMethod(5); 
    new Thread(instance).start(); 
    new Thread(instance).start(); 
} 
} 
Các vấn đề liên quan