2010-06-07 27 views
8

Sau khi giới thiệu Mô hình bộ nhớ Java, các nguyên tắc Swing đã được thay đổi để cho biết rằng bất kỳ thành phần Swing nào cần được khởi tạo trên EDT để tránh trạng thái cá thể không được xuất bản.Có được phép tải các lớp Swing trong chuỗi không phải là EDT không?

Điều tôi không thể tìm thấy ở bất cứ nơi nào liệu việc tải lớp cũng được bắt buộc phải có trên EDT hay chúng tôi có thể tải trước các khóa Swing chính trong chuỗi nền? Có bất kỳ tuyên bố chính thức nào từ Sun/Oracle về vấn đề này không? Có bất kỳ lớp nào được biết là giữ trạng thái tĩnh không an toàn, do đó cần được tải trên EDT không?

Làm rõ để giải quyết câu hỏi của Nemi: đây là vấn đề thực tế. Một phần đáng kể thời gian khởi động ứng dụng của chúng tôi, được dành cho việc nạp lớp và tải phông chữ/hình ảnh trên EDT. Hầu hết điều này có thể được quy cho Swing và các thư viện liên quan.

Dưới đây là nền nền: Như nhiều ứng dụng Swing khác, khi khởi động, chúng tôi đang xây dựng sẵn nhiều biểu mẫu để làm cho giao diện người dùng phản hồi nhanh hơn. Sau khi profiling, chúng tôi thấy rằng thời gian thực tế để xây dựng biểu mẫu tương đối nhanh - tải chậm của tất cả các lớp và phông chữ (đọc đĩa là chậm trong thiết lập của công ty bằng máy quét vi-rút, trình theo dõi giám sát, trình theo dõi kiểm tra và thiên thần biết những gì khác tacked trên trình điều khiển HDD).

Chúng tôi đã cố gắng tạo các biểu mẫu giống nhau trong một chuỗi nền (vi phạm các quy tắc của Swing) và sau đó vứt chúng đi. Khi chúng ta hoàn thành, chúng ta xây dựng các biểu mẫu giống nhau trên EDT, nhanh hơn nhiều khi tất cả các lớp được nạp và bất kỳ tệp nào khác nằm trong bộ đệm đĩa. Nó làm việc cho chúng tôi, và chúng tôi có thể sẽ tiếp tục làm điều đó trừ khi một cái gì đó thực sự xấu xảy ra.

Điều tôi đang hỏi liệu đây có phải là thực hành an toàn, thực hành tốt hay hack?

+0

Đặc biệt, hai lớp singleton tôi có thể nghĩ đến là UIManager và AppContext. Cả hai javadocs không cho biết liệu chúng được coi là threadsafe. Giao diện của AppContext được đồng bộ hóa đúng cách, ngoại trừ phương thức isDisposed() không đọc trạng thái đúng (cần đồng bộ hóa). UIManager là miễn phí cho tất cả, mặc dù một khi EDT bắt đầu, tôi không nghĩ rằng bất kỳ chủ đề nào khác sẽ làm thay đổi nó. – ddimitrov

+0

Đây là một câu hỏi thú vị. Nó hoàn toàn là học vấn, hay là có một vấn đề thực sự mà bạn đang cố giải quyết? Tôi không thể nghĩ ra một lý do chính đáng nào bạn muốn làm điều này. – Nemi

+0

@Nemi, bổ sung thêm ngữ cảnh cho câu hỏi – ddimitrov

Trả lời

2

Bằng chứng dường như cho thấy nó là an toàn - nhưng sau đó một lần nữa, như ddimitrov nói trong các ý kiến ​​- tỷ lệ cược có lợi cho việc không tìm lỗi lỗi tinh vi do thay đổi không được xuất bản bởi vì máy điển hình chỉ có một vài lõi, và Cache L2/L3 được chia sẻ. (L1 cache là mỗi lõi, nhưng chúng ta rất nhỏ.)

Nếu bạn muốn đảm bảo không có vấn đề phát sinh do tải lớp nền, thì có thể an toàn nhất để gắn vào các lớp tải trên ETD. Để duy trì giao diện người dùng trực tiếp, hãy tạo trình nạp lớp tùy chỉnh cũng bơm các sự kiện ở giữa tải mỗi lớp. (Dependencies được nạp lại entrantly vì vậy sự chậm trễ sẽ chỉ trong thời gian tải chỉ là một lớp.) Giả sử trình nạp lớp này được đóng gói với ứng dụng của bạn, sau đó nó có thể đơn giản trì hoãn việc nạp tất cả các lớp vào trình nạp lớp của nó.

Ngoài ra, hàng đợi sự kiện phụ có thể được mở rộng chạy trên các chuỗi riêng biệt (ví dụ: hộp thoại phương thức và thư viện spin). Điều này ngụ ý Swing có thể chạy trên bất kỳ chuỗi nào, miễn là nó chạy trên chỉ một, và có nghĩa là nó phải cập nhật nhất quán (hoặc tất cả chúng ta đều rất may mắn!) Trên cơ sở này, bạn có thể tải các lớp học của bạn trên EDT chính, và bắt đầu một EDT phụ để bơm các sự kiện giao diện người dùng, giữ cho UI đáp ứng - theo cùng một cách thức một chức năng hộp thoại phương thức. Tiện ích Spin sẽ bơm các sự kiện EDT cho bạn, hoặc bạn có thể sinh ra một EDT mới bằng tay.

+0

Cảm ơn, điều này trả lời câu hỏi của tôi. – ddimitrov

+0

Suy nghĩ về nó, chạy Swing trên một EDT mới toanh sinh ra từ cái cũ là an toàn, bởi vì Thread.start() là một ấn phẩm an toàn. Sau đó, để xem những thay đổi chúng ta cần hoặc là Thread.join() các dispatcher tạm thời hoặc spawn nhưng một dispatcher khác (sẽ thấy các lớp mới nạp) và giết EDT cũ. Âm thanh lộn xộn ... – ddimitrov

+0

Nếu bạn sử dụng thư viện Spin, các chi tiết sẽ được xử lý. Tôi không nghĩ rằng nó khá là lộn xộn như bạn lo sợ - EDT thứ cấp có thể được chấm dứt bằng cách đăng một sự kiện với nó. Bạn làm điều này, và Thread.join() sau khi tải tất cả các lớp. – mdma

0

Mặc dù bạn chính xác về mặt kỹ thuật - Tôi chưa bao giờ nghe về sự cố khi hiển thị biểu mẫu trong một chuỗi khác miễn là bạn không làm bất kỳ điều gì với chúng sau khi được nhận ra ngoại trừ với EDT (theo mặt trời) hướng dẫn ban đầu).

Những người từng là hướng dẫn của mặt trời nhưng Sun đã thay đổi chúng theo như bạn đã chỉ định - vì vậy tôi chắc chắn ai đó đã tìm thấy hoặc tạo ra xung đột tiềm ẩn, nhưng tôi cũng chắc chắn sẽ rất khó để truy cập. vẫn hoạt động và hầu như không tuân thủ các nguyên tắc đó.

Đối với câu hỏi của bạn, tôi chắc chắn bạn có thể tải các lớp miễn là bạn không khởi tạo bất kỳ đối tượng nào và vẫn nằm trong ngay cả các nguyên tắc nghiêm ngặt nhất.

EDT chỉ được sử dụng để tránh va chạm chủ đề vì Swing là đơn luồng (theo thiết kế). Nếu bạn chỉ tải các lớp và không instantiating bất kỳ, bạn không phải là mở mình cho bất kỳ vấn đề luồng.

+0

Điều khiến tôi lo lắng là trạng thái tĩnh. Quy tắc EDT giải quyết vấn đề nguyên tử, nhưng không quan tâm đến khả năng hiển thị - thiết lập trường thành giá trị trong một chuỗi không được đảm bảo hiển thị từ chuỗi khác trừ khi xuất bản đúng cách (ví dụ: đồng bộ hóa, CAS, v.v.) . Lưu ý rằng ngay bây giờ, cơ hội là prety cao mà hai chủ đề sẽ được lên kế hoạch trên cùng một CPU. Với sự ra đời của các hệ thống đa lõi, vấn đề sẽ trở nên quan trọng. – ddimitrov

+0

@ddimitrov Điều này cho đến khi nó được nhận ra, có rất ít cơ hội mà bất kỳ chủ đề nào khác sẽ có quyền truy cập vào nó. Bây giờ, phải có một số cơ hội, nhưng chỉ đơn giản là tải các lớp học không thể gây ra một vấn đề vì không có mã đang chạy bên trong các lớp học được nêu ra. Tôi không chắc chắn những gì (nếu có) bạn không đồng ý với. Khi bạn thực sự khởi tạo nó - và mãi mãi sau đó - bạn chỉ nên sử dụng EDT, điều đó không ngụ ý rằng EDT phải được sử dụng để tải các lớp học là câu hỏi của OP. –

+0

Khi bạn nạp các lớp bất kỳ bộ khởi tạo tĩnh nào chạy trong chuỗi tải và bất kỳ trạng thái tĩnh không phải là cuối cùng nào đều phải tuân theo các quy tắc xuất bản an toàn. Tôi tin rằng không có nhiều trạng thái tĩnh có thể thay đổi trong Swing, nhưng (như tôi đã đưa ra ví dụ) có một số. Nếu không, tôi đồng ý rằng cơ hội cho một vấn đề là thấp, nhưng khi có một vấn đề nó sẽ không thể chẩn đoán hoặc thậm chí tái sản xuất đáng tin cậy. – ddimitrov

2

Nó an toàn. Xem: http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html (quy tắc chuỗi đơn)

Nếu bạn sợ hoặc muốn một số phản hồi/gỡ lỗi, hãy xem công cụ FEST/Swing này: http://fest.easytesting.org/swing/wiki/pmwiki.php?n=FEST-Swing.EDT ("Kiểm tra truy cập vào các thành phần GUI được thực hiện trong EDT") - đó là tùy chỉnh RepaintManager không thành công khi bạn vi phạm chính sách truy cập EDT.

Bạn có thể tìm thấy điều này hữu ích cũng như: http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html

Họ không đề cập đến lớp tải một cách rõ ràng, nhưng họ giải thích những gì các chính sách truy cập EDT là về.

+0

Một lần nữa tôi không nói về các vi phạm chính sách EDT ở đây. Chính sách EDT không phải là một quy tắc tùy tiện, nó có lý do và tôi có cảm giác rằng nó không hoàn chỉnh. Xem câu trả lời của mdma để biết thêm chi tiết. – ddimitrov

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