2012-06-26 13 views
7

Theo hiểu biết của tôi, một thùng chứa servlet tạo ra các phiên bản giới hạn của các servlet và nhiều luồng của mỗi cá thể servlet và sử dụng lại các chủ đề và các cá thể đó.Tại sao chủ đề EJBs an toàn và servlet không?

Vì có nhiều phiên bản của một chuỗi, chúng không phải là "An toàn chủ đề" (mặc dù tôi hiểu rằng việc mã hóa chúng với An toàn luồng không khó).

Hộp chứa EJBs không tạo chuỗi EJB, nhưng chỉ sử dụng lại các đối tượng EJB (sử dụng pool). Vì không có nhiều luồng của một cá thể EJB, nên không có câu hỏi về sự an toàn của luồng.

Câu hỏi của tôi: Tại sao có hành vi khác? Nó không phải là một ý tưởng tốt để làm cho EJB hoạt động như Servlets (thread không an toàn)?

Tôi chắc chắn rằng tôi đang thiếu thứ gì đó và muốn hiểu phần còn thiếu.

+0

Tại sao chúng phải nhất quán? Họ làm những việc hoàn toàn khác nhau. – EJP

+0

@EJP, Phải, họ giải quyết các mục đích khác nhau, nhưng họ có sự tương đồng về mặt không quốc tịch. Với sự tương tự này, các EJB có thể làm cho hiệu suất hoạt động hiệu quả hơn nhờ có các luồng thay vì chỉ có các cá thể. –

+0

Nếu bạn quan tâm đến một servlet/một ví dụ - bạn hãy xem bài đăng này: http://piotrnowicki.com/2012/04/one-servlet-instance-to-rule-them-all/ –

Trả lời

8

Có lẽ vì chúng không được thiết kế với cùng mục tiêu.

API servlet là một API đơn giản, rất gần với giao thức HTTP, trên đó bạn có thể xây dựng các ứng dụng hoặc khung công tác. Giao thức HTTP hoàn toàn phi trạng thái, tôi đoán có ý nghĩa khi xây dựng một API không trạng thái. Một số khung công tác được xây dựng trên đầu trang của API servlet (ví dụ: Sọc), sử dụng một phiên bản Hành động cho mỗi yêu cầu, không được sử dụng đồng thời.

EJB là một khung công tác phức tạp và cao cấp hơn, được thiết kế để triển khai logic nghiệp vụ giao dịch càng đơn giản càng tốt. Đó là nặng hơn, và có các thành phần stateful. Đây rõ ràng là cần phải được an toàn thread. Tôi đoán nó là như vậy tự nhiên để làm cho đậu không quốc gia thread-an toàn là tốt. Ví dụ:

Cần lưu ý rằng các hạt mùa xuân là các trình đơn mặc định và do đó phải tuân thủ các quy tắc giống như các servlet. Vì vậy, nhiều thiết kế có thể cung cấp nhiều hơn hoặc ít hơn các chức năng tương tự.

Chủ đề không có gì để làm với tối ưu hóa hiệu suất. Nếu bạn cần xử lý 3 yêu cầu đồng thời, bạn cần 3 luồng, cho dù yêu cầu đến một servlet hay đến một EJB.

+2

Cả hai Servlet và EJB đều có thể bắt đầu/cam kết các giao dịch và cả Java EE 6 đều có thể là đa luồng. Nó thực sự là một vấn đề của nhóm chuyên gia EJB thận trọng hơn với các quyết định tương tự như nhóm chuyên gia Servlet - cho đến vài năm gần đây. Trong EJB 3.2, chúng tôi hoàn toàn loại bỏ được giới hạn giả định "không thể sử dụng tệp" mà không bao giờ nên có nhiều hơn một đề xuất và nên có trong đặc tả EE hơn là thông số EJB. –

+0

Cảm ơn JB vì lời giải thích chi tiết. Tôi hiểu rằng Servlets thường có trọng lượng nhẹ so với EJB. Nhưng mặt khác, các EJB không trạng thái (là loại EJB phổ biến nhất) cung cấp chức năng tương tự và không giả sử để lưu trữ bất kỳ trạng thái nào. Tương tự như các servlet, các EJB có thể dễ dàng được viết theo cách 'an toàn chủ đề'. Vì, điều này có thể thực hiện được, việc tạo các luồng có hiệu quả hơn nhiều so với việc tạo các cá thể. Đúng không? –

+2

Trước hết, đậu không quốc tịch có thể có trạng thái. Họ không thể có trạng thái đàm thoại, điều này rất khác. Thứ hai, như David Blevins giải thích trong câu trả lời của mình, bạn có thể sử dụng đơn, tương tự như servlet. Thứ ba, các luồng được sử dụng trong các EJB và các servlet để xử lý các yêu cầu đồng thời. Sự khác biệt duy nhất là một cá thể servlet đơn được sử dụng bởi tất cả các luồng đồng thời, trong khi một EJB chỉ được sử dụng bởi một luồng tại một thời điểm. Tại sao làm cho bạn nghĩ rằng việc tạo ra một cá thể đậu là tốn kém như vậy? Tạo một đối tượng trong Java có nhiều thứ tự độ lớn nhanh hơn việc thực thi một truy vấn SQL chẳng hạn. –

3

câu trả lời của bạn tốt nhất là thẳng ra khỏi Javadoc cho giao diện javax.servlet.SingleThreadedModel:

Deprecated. Như của Java Servlet API 2.4, không có thay thế trực tiếp.

public interface SingleThreadModel

Đảm bảo rằng servlets chỉ xử lý một yêu cầu tại một thời điểm. Giao diện này không có phương thức.

Nếu servlet thực hiện giao diện này, bạn được đảm bảo rằng không có hai luồng nào sẽ thực hiện đồng thời trong phương thức dịch vụ của servlet. Thùng chứa servlet có thể thực hiện việc bảo đảm này bằng cách đồng bộ hóa quyền truy cập vào một cá thể đơn của servlet, hoặc bằng cách duy trì một nhóm các cá thể servlet và gửi mỗi yêu cầu mới tới một servlet miễn phí.

Lưu ý rằng SingleThreadModel không giải quyết tất cả các sự cố về an toàn chủ đề. Ví dụ, các thuộc tính phiên và các biến tĩnh vẫn có thể được truy cập bởi nhiều yêu cầu trên nhiều luồng cùng một lúc, ngay cả khi các servlet SingleThreadModel được sử dụng.Chúng tôi đề nghị một nhà phát triển sử dụng các phương tiện khác để giải quyết những vấn đề đó thay vì thực hiện giao diện này, chẳng hạn như tránh sử dụng biến mẫu hoặc đồng bộ hóa khối mã truy cập các tài nguyên đó. Giao diện này không được chấp nhận trong phiên bản API Servlet 2.4.

8

Câu trả lời ngắn nhất cho câu hỏi của bạn là tất nhiên nó là một ý tưởng tốt để làm cho nó có thể cho các EJB để làm việc như Servlets và trong EJB 3.1 chúng tôi đã thêm một thành phần có thể làm chính xác điều đó: @Singleton

Một @Singleton đậu có thể được đa luồng như một servlet, bởi một trong hai:

  • Sử dụng @ConcurrencyManagement(BEAN)
  • Sử dụng @ConcurrencyManagement(CONTAINER) cùng với @Lock(READ) về phương pháp trong trường hợp đồng thời là mong muốn và @Lock(WRITE) trên các phương pháp không phải là chủ đề an toàn.

Một điều khác mà Servlets đã có trong nhiều năm mà EJB chưa từng có là <load-on-startup> cho phép Servlet tải háo hức và làm việc lúc bắt đầu ứng dụng.

Để khớp với Servlet <load-on-start>, chúng tôi đã thêm chú thích @Startup có thể được thêm vào bất kỳ @Singleton EJB nào và sẽ bắt đầu khi ứng dụng bắt đầu. Những hạt đậu này sẽ có phương thức @PostConstruct được gọi khi ứng dụng bắt đầu và @PreDestroy được gọi khi ứng dụng tắt. Thay vì sử dụng một số (<load-on-startup>1</load-on-startup>) để chỉ ra thứ tự mà đậu được chú thích với số @Startup bắt đầu, bạn có thể chú thích đậu với @DependsOn và chỉ định danh sách các hạt cần phải bắt đầu trước bean được chú thích.

Và một khía cạnh ít được biết đến và hiểu hơn chúng tôi đã làm trong EJB 3.1 để căn chỉnh Servlets và EJB là cho phép EJB được đóng gói bên trong các tệp .war - đó không phải là phần ít được biết đến hơn. chúng tôi lặng lẽ thay đổi định nghĩa của java:comp/env để phù hợp với phương pháp Servlet.

Trước EJB 3.1 không có cách nào có thể có hai EJB chia sẻ không gian tên java:comp/env (java:comp/env là phạm vi đậu trong thông số EJB). Servlets, ngược lại, không bao giờ có bất kỳ cách nào để Servlets riêng lẻ có không gian tên riêng của riêng mình java:comp/env (java:comp/env được mô tả theo mô đun Servlet). Vì vậy, trong EJB 3.1 một EJB được đóng gói trong một cuộc chiến sẽ có cùng một không gian tên java:comp/env phạm vi mô-đun tương tự như tất cả các Servlet và EJB khác trong webapp, một sự tương phản khá lớn với không gian tên đậu java:comp/env đậu mà EJB nhận được khi được đóng gói một EAR bên ngoài chiến tranh. Chúng tôi tranh luận về điều đó một tuần.

Một chút thời gian ngắn để thưởng thức bạn bè của bạn.

+0

Đây là một tin tuyệt vời đối với tôi rằng EJB trong JEE6 đang cung cấp tùy chọn cho nhiều luồng. Điều này làm tôi hài lòng vì sự hiểu biết của tôi đang đi đúng hướng :) –