2010-05-06 23 views

Trả lời

8

Bằng cách này bạn tách việc tính toán (những gì) từ việc thực hiện (khi và/hoặc cách sự).

Với Runnable hoặc Callable, bạn có thể gửi nhiều công việc/tính toán đến một số Executor để đảm bảo sắp xếp các nội dung. Dưới đây là một hình thức trích đoạn ExecutorService:

pool = Executors.newFixedThreadPool(poolSize); 
... 
pool.execute(new Handler(serverSocket.accept())); 
... 
class Handler implements Runnable { 
    ... 
} 

Sử dụng Runnable/Callable giúp bạn linh hoạt hơn rằng việc sử dụng Chủ đề trực tiếp.

+0

cũng như vậy runnable của bạn có thể mở rộng các lớp không phải là chủ đề khác –

2

Nó có thể không có ý nghĩa gì trong hệ thống phân cấp kế thừa của bạn để mở rộng Thread. Chỉ mở rộng Thread nếu bạn muốn sửa đổi chức năng của Thread s.

Với Runnable, bất kỳ lớp nào trong bất kỳ phân cấp thừa kế nào cũng có thể hiển thị công việc có thể được xem là đơn vị hoạt động để thực hiện Thread.

3

Vì IS-A thực sự không phải là thứ bạn muốn. Lớp học của bạn muốn được Runnable, nhưng IS-A Thread cảm thấy quá mạnh. Đó là những gì thừa kế đang nói. Bạn thực sự chỉ muốn thực hiện phương thức run(), không phải tất cả các công cụ tham dự khác trong lớp Thread.

Điều này rơi phù hợp với Scott Meyers lời khuyên rất tốt trong "Hiệu quả hơn C++": Làm cho các lớp không lá trừu tượng. Thay thế giao diện và bạn đang phát hiện.

18

Điểm thực tế cần lấy đi là các dụng cụ được LUÔN LUÔN được ưu tiên mở rộng trên mọi trường hợp có vấn đề.

Mở rộng liên kết hai tệp lớp rất chặt chẽ và có thể gây khó khăn cho việc xử lý mã.

Khi tôi lần đầu tiên "hiểu" lập trình OO, tôi đã mở rộng mọi thứ, nhưng nó đã biến toàn bộ thiết kế của tôi thành đồ sộ. Bây giờ tôi chỉ mở rộng một vài điều rõ ràng và rõ ràng là vượt qua bài kiểm tra "is-a" và mọi thứ khác là một giao diện ...

Nhiều vấn đề chỉ dừng lại xảy ra (Khó hiểu nhiều tình huống thừa kế, thời gian tái cấu trúc lãng phí thời gian, xu hướng có các biến "được bảo vệ", sau đó tự hỏi tại sao chúng thay đổi khi bạn không thay đổi chúng trong lớp hiện tại, yêu cầu chuỗi cho các nhà xây dựng, tìm ra cách các cây thừa kế khác nhau tương tác với nhau ...

It có vẻ như cứ 3 năm một lần (trong 20 năm qua) tôi nghĩ tôi thực sự "lập trình" và nhìn lại những điều ngu ngốc mà tôi đã làm 3 năm trước trong sự xấu hổ ...Đây là một trong những trường hợp đó (nhưng từ gần 7 năm trước vào thời điểm này)

2

Những lý do tại sao bạn có thể thích thực hiện Interface Runnable để mở rộng Class Thread như sau:

  • ít overhead trong một bối cảnh sequencial (source)

Khi bạn mở rộng lớp thread, mỗi chủ đề của bạn tạo ra độc đáo obj ect và liên kết với nó. Khi bạn triển khai Runnable, nó chia sẻ cùng một đối tượng cho nhiều chuỗi.

Nguồn: a blog - Tôi không hoàn toàn chắc chắn nếu đó là đúng

  • bạn có thể gửi nhiệm vụ qua mạng với Runnable (Chủ đề không serializable, source)
  • tốt hơn OOP kiểu
    • rất có thể bạn không có mối quan hệ "là" "
    • bạn có khả năng mở rộng các lớp khác (Java không có nhiều thừa kế)
0

Để trả lời câu hỏi đầu tiên:

Nếu bạn mở rộng chủ đề, một thể hiện của lớp (chủ đề mở rộng) của bạn sẽ luôn gọi hàm tạo của chuỗi siêu lớp. Vì vậy, MyClass myclass = new MyClass() sẽ luôn gọi "super()" bên trong constructor của MyClass, tạo một chuỗi, và cuối cùng bạn có thể thực hiện một số phí vào lớp của bạn (nếu bạn không sử dụng bất kỳ phương thức nào chuỗi siêu lớp). Vì vậy, việc triển khai Runnable chỉ cho phép lớp của bạn chạy nhanh hơn mà không cần bất kỳ chi phí thừa kế nào.

Hơn nữa, có một số câu trả lời sai ở đây:

Bây giờ tôi mở rộng chỉ là vài điều mà rõ ràng và rõ ràng là vượt qua "là-một" thử nghiệm và mọi thứ khác là một giao diện ...

Bạn chưa bao giờ cân nhắc tạo một đối tượng không có giao diện? Bởi vì sẽ rất sai khi thực hiện một giao diện cho mọi đối tượng!

Khi bạn mở rộng lớp Thread, mỗi chuỗi của bạn tạo đối tượng duy nhất và liên kết với nó. Khi bạn thực hiện Runnable, nó chia sẻ cùng một đối tượng với nhiều luồng.

Sai, mỗi khi bạn gọi hàm tạo của một lớp, bạn sẽ nhận được một đối tượng riêng, không quan trọng từ nơi nó được mở rộng hoặc những gì nó triển khai!

Kết luận: Trong java, EVERY class instance là một đối tượng và mở rộng Object class (trong khi nguyên thủy thì không ...chỉ các mảng nguyên thủy như các lớp int [] mở rộng Object, và các mảng như vậy có cùng các phương thức giống như bất kỳ đối tượng nào - nhưng đáng tiếc chúng không được đề cập trong Javadoc! Các anh chàng Mặt trời có lẽ không muốn chúng tôi sử dụng chúng).

Btw có ít nhất hai lợi thế của thừa kế: Chia sẻ mã và Javadoc rõ ràng. Bởi vì nếu bạn kế thừa từ một lớp, bạn có thể thấy tất cả các lớp con trong Javadoc. Bạn có thể làm điều đó với một giao diện quá, nhưng sau đó bạn không thể chia sẻ mã. Thậm chí nhiều hơn, bạn sẽ cần phải tạo các đối tượng "lồng nhau" và gọi hàm tạo của hai hoặc nhiều đối tượng thay vì chỉ một, và điều này một lần nữa có nghĩa là bạn thực hiện một số chi phí từ chính đối tượng siêu lớp! Bởi vì không có đối tượng trong Java mà không có chi phí, và việc tạo ra các đối tượng ít nhất có thể là khá quan trọng đối với các ứng dụng hiệu suất cao. Đối tượng là điều tuyệt vời nhất, nhưng các đối tượng không cần thiết không phải là ...

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