2008-09-17 27 views
10

là hợp pháp đối với một chuỗi để gọi this.start() bên trong hàm tạo riêng của nó? và nếu vậy thì những vấn đề tiềm ẩn có thể gây ra điều gì? Tôi hiểu rằng đối tượng sẽ không được khởi tạo đầy đủ cho đến khi hàm tạo đã chạy để hoàn thành nhưng ngoài việc này còn có bất kỳ vấn đề nào khác không?gọi thread.start() trong hàm tạo riêng của nó

Trả lời

1

Đó là hợp pháp nhưng không khôn ngoan. Phần Thread của instance sẽ được khởi tạo hoàn toàn, nhưng constructor của bạn có thể không. Có rất ít lý do để mở rộng Chủ đề, và để kéo các thủ thuật như thế này sẽ không giúp mã của bạn.

2

Tôi giả định rằng bạn muốn thực hiện điều này để làm cho mã của bạn ít tiết; thay vì nói

Thread t = new CustomThread(); 
t.start(); 
activeThreads.add(t); 

bạn chỉ có thể nói

activeThreads.add(new CustomThread()); 

Tôi cũng giống như có ít rườm rà, nhưng tôi đồng ý với trả lời khác mà bạn không nên làm điều này. Cụ thể, nó phá vỡ quy ước; bất kỳ ai quen thuộc với Java, người đọc ví dụ thứ hai sẽ giả định rằng luồng chưa được bắt đầu. Tệ hơn nữa, nếu họ viết mã luồng riêng của họ tương tác một cách nào đó với bạn, sau đó một số chủ đề sẽ cần phải gọi start và những người khác sẽ không. Điều này có vẻ không hấp dẫn khi bạn làm việc một mình, nhưng cuối cùng bạn sẽ phải làm việc với những người khác, và tốt để phát triển thói quen viết mã tốt để bạn có thời gian làm việc dễ dàng với người khác và mã được viết với các quy ước tiêu chuẩn.

Tuy nhiên, nếu bạn không quan tâm đến các quy ước và ghét sự dư thừa thêm, hãy tiếp tục; điều này sẽ không gây ra bất kỳ sự cố nào, ngay cả khi bạn cố gọi số start nhiều lần do nhầm lẫn.

2

Bằng cách này, nếu ai muốn rườm rà thấp hơn và vẫn giữ các nhà xây dựng với ngữ nghĩa "tiêu chuẩn" của nó, người ta có thể tạo ra một phương pháp nhà máy:

activeThreads.add(CustomThread.newStartedThread()); 
+0

điều này liên quan đến câu hỏi của OP như thế nào? – subsub

1

"hợp pháp", nhưng tôi nghĩ vấn đề quan trọng nhất là: Một lớp học nên làm một việc và làm tốt.

Nếu lớp học của bạn sử dụng một chuỗi nội bộ, thì sự tồn tại của chuỗi đó sẽ không hiển thị trong API công khai. Điều này cho phép cải tiến mà không ảnh hưởng đến API công khai. Giải pháp: mở rộng Runnable, không phải Thread.

Nếu lớp học của bạn cung cấp chức năng chung, trong trường hợp này, xảy ra để chạy trong một chuỗi, sau đó bạn không muốn giới hạn bản thân để luôn luôn tạo chuỗi. Cùng một giải pháp ở đây: mở rộng Runnable, không phải Thread.

Đối với độ chi tiết ít hơn, tôi thứ hai đề xuất sử dụng phương pháp nhà máy (ví dụ: Foo.createAndRunInThread()).

13

Vì lý do an toàn cho bộ nhớ, bạn không nên để một tham chiếu đến đối tượng hoặc trường của đối tượng đó đến một chuỗi khác từ bên trong hàm tạo của nó. Giả sử rằng chuỗi tùy chỉnh của bạn có các biến mẫu, bằng cách khởi động nó từ bên trong hàm tạo, bạn được bảo đảm vi phạm các nguyên tắc của Mô hình Bộ nhớ Java. Xem Brian Goetz's Safe Construction Techniques để biết thêm thông tin.

+1

Nhận xét về câu trả lời này? Nó không phải là không chính xác. –

+1

Downvote? Xin vui lòng trang web một nguồn nếu bạn nghĩ rằng điều này là sai. Chính xác. –

+0

Câu trả lời hoàn toàn không được đóng hộp. Trừ khi bạn sử dụng hàm khởi tạo Runnable, bạn có thể tham chiếu 'this' từ bên trong' Thread # run' trước khi hàm khởi tạo hoàn thành, vi phạm các quy tắc an toàn bộ nhớ. Vì vậy, bạn phải cẩn thận. –

3

Bạn cũng sẽ thấy các vấn đề đáng sợ nếu lớp Thread được thêm lớp con. Trong trường hợp đó, bạn sẽ kết thúc với luồng đang chạy một khi các lối thoát super() và bất kỳ thứ gì mà lớp con có thể làm trong hàm tạo của nó có thể không hợp lệ.

@bill barksdale Nếu chuỗi đã chạy, gọi lại bắt đầu giúp bạn nhận được một IllegalThreadStateException, bạn không nhận được 2 chuỗi.

1

Pháp lý ... có (với các lời nhắc như đã đề cập ở nơi khác). Có thể tư vấn ... không.

Tôi chỉ là mùi mà bạn chỉ có thể dễ dàng tránh được. Nếu bạn muốn chủ đề của mình tự động bắt đầu, chỉ cần thực hiện như sau: Heinz Kabutz.

public class ThreadCreationTest { 
    public static void main(String[] args) throws InterruptedException { 
    final AtomicInteger threads_created = new AtomicInteger(0); 
    while (true) { 
     final CountDownLatch latch = new CountDownLatch(1); 
     new Thread() { 
     { start(); } // <--- Like this ... sweet and simple. 
     public void run() { 
      latch.countDown(); 
      synchronized (this) { 
      System.out.println("threads created: " + 
       threads_created.incrementAndGet()); 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       Thread.currentThread().interrupt(); 
      } 
      } 
     } 
     }; 
     latch.await(); 
    } 
    } 
} 
Các vấn đề liên quan