2012-04-09 25 views
5

Trong Java util logging, tôi khởi tạo trình xử lý trên init() và đóng trình xử lý tại destroy() và nó hoạt động hoàn toàn tốt đẹp: vv Nếu người dùng làm mới trang bình thường, nó vẫn chỉ tạo một tệp nhật ký.Java applet: Làm thế nào để chắc chắn phá hủy được hoàn thành trước khi làm mới trang

Tuy nhiên, nếu người dùng làm mới trang bằng applet nhanh gấp đôi, có vẻ như lệnh hủy() không được gọi hoặc có thể chưa hoàn thành tác vụ và vì init() được gọi lại, giả sử tập tin trước đó vẫn bị khóa và tạo một tệp nhật ký mới.

Tôi đã cố gắng sử dụng cả destroy() và finalize() để đóng trình xử lý nhưng nó không hoạt động. Bất cứ ai cũng có ý tưởng làm thế nào để giải quyết vấn đề này?

Một câu hỏi nhỏ khác là: Điều gì thực sự xảy ra nếu init() chưa hoàn tất và trang được làm mới. Nó sẽ tiếp tục quá trình và cuối cùng thất bại để gọi phá hủy() hoặc nó chỉ dừng lại ở đó?

+0

Bạn có thể thêm vào mã câu hỏi của phương thức "init" và "destroy" không? Ít nhất là các bộ phận về trình xử lý nhật ký. –

Trả lời

4

Trích từ Java Tutorials:

Các-in cắm phần mềm Java tạo ra một sợi công nhân cho mỗi Java applet.

Trong môi trường đa luồng, bạn nên rất cẩn thận với tài nguyên được chia sẻ. Cách tiếp cận tốt nhất và dễ nhất là không chia sẻ bất cứ điều gì (quy mô tốt nhất và không có deadlocks có thể).

Tôi giả định rằng bạn khởi tạo trình xử lý của mình mỗi lần trong "init" -method. Nếu đó là sự thật, bạn nên sử dụng một trình ghi nhật ký được chia sẻ tĩnh (kiểm tra điều này link). Nó sẽ giúp cải thiện tình hình một chút, nhưng nếu bạn bắt đầu nhiều hơn một trình duyệt với applet của bạn - tệp nhật ký mới vẫn sẽ được tạo ra. Và cách giải quyết này không được Oracle khuyến cáo và được bảo tồn cho khả năng tương thích ngược.


Đề xuất và dễ thực hiện giải pháp - "mỗi applet phải có nhật ký riêng và ghi vào tệp riêng". Mã để tạo tên tệp nhật ký:

private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); 

private String generateFileName() { 
    return String.format("applets-log/%s-%s.log", dateFormat.format(new Date()), UUID.randomUUID()); 
} 

Ngoài ra, Best Practices For Applet Development.


trả lời cho câu hỏi nhỏ của bạn (thay đổi):

Theo thảo luận về old bug này trong plugin java, Applet có thể được chấm dứt vào bất kỳ thời điểm với một số khoảng thời gian được xác định trước để dọn dẹp. Vì vậy, bạn nên đặt mã làm sạch tài nguyên trong phương thức "stop" hoặc "destroy" của mình, nhưng bạn không nên dựa vào mã đó sẽ được thực thi.

Vòng đời Applet được kiểm soát bởi trình duyệt và ứng dụng không được là khả năng được chạy khi tài liệu lưu trữ bị hủy bởi trình duyệt .

Kể từ 6u10, cả plugin cũ và plugin mới thực thi tắt applet sau một khoảng thời gian cố định (1000ms trong plugin cũ và 200ms trong plugin mới ) cho applet dừng.

+0

Đó là những gì tôi đã nói. –

0

Hy vọng bạn không thử nghiệm trong FF. Đọc ở đây: https://bugzilla.mozilla.org/show_bug.cgi?id=638070

+0

đó không phải là trường hợp, như applet hoạt động hoàn toàn bình thường, không có vấn đề bao nhiêu lần bạn nhấn làm mới, applet vẫn hoạt động. Nó chỉ là nó không giết các tập tin lck, và gây ra để tạo ra nhiều tập tin đăng nhập – Harts

0

Bạn vừa chạy vào giới hạn cơ bản với môi trường nhiều luồng.

Bạn thực sự không thể biết khi nào destroy() hoặc finalize() sẽ được gọi là tương đối so với các chủ đề khác. Khi trình duyệt tải lại trang, trình duyệt có thể tải applet trong một chuỗi mới. Nếu người dùng truy cập tải lại hai lần nhanh, nó có thể tạo 2 chủ đề mới, gọi số init() trên số thứ 2 (người dùng thực sự thấy) trước khi gọi init() trên người dùng không bao giờ thấy trước khi gọi destroy() trên phiên bản trước. Ở đầu kia của vòng đời, finalize() được gọi bởi luồng thu gom rác có thể rất dài sau khi đối tượng không còn cần thiết nữa. Bạn đang làm việc trong một môi trường đa luồng và bạn không thể dựa vào bất kỳ thứ tự hoạt động nào giữa các luồng.

Để báo Javadoc:

Một Applet là một chương trình nhỏ mà được thiết kế để không thể chạy trên riêng của mình, nhưng thay vì được nhúng bên trong một ứng dụng khác.

Đây thực sự là ứng dụng bên ngoài nên kiểm soát việc tạo/mở và đóng nhật ký nếu bạn chỉ có một tệp nhật ký. Nếu ứng dụng bên ngoài là trình duyệt web, thì bạn không thể giải quyết vấn đề bạn đang gặp phải. Sau đó, một lần nữa, nếu bạn đang chạy applet trong trình duyệt web, bạn không nên ghi nhật ký vào hệ thống tệp. Đó chỉ là hành vi bất lịch sự nói chung.

Nếu bạn hoàn toàn phải có tệp nhật ký cho các ứng dụng bên trong trình duyệt web, giải pháp dễ nhất là cho mỗi cuộc gọi đến init() để tạo tệp mới cụ thể cho yêu cầu đó của applet. Nếu bạn muốn tham vọng, bạn có thể sử dụng các tệp khóa để chỉ định tệp nào đang được sử dụng và tại thời điểm destroy() nối các tệp nhật ký đã mở vào một tệp lớn hơn, nhưng sau đó lại có vấn đề phối hợp các quy trình nối trên các luồng.

+0

Bạn đang sai về 'Nếu ứng dụng bên ngoài là một trình duyệt web, thì bạn không thể giải quyết vấn đề bạn đang gặp phải '. Khung công tác ghi nhật ký (JUL, log4j và v.v.) là an toàn chỉ để sử dụng. Vì vậy, vấn đề có thể được giải quyết bằng cách sử dụng tĩnh chia sẻ logger sẽ được sử dụng bởi tất cả các trường hợp của applet. –

+0

@Vadim bạn không thể đảm bảo trình duyệt sẽ chỉ gọi trình khởi chạy tĩnh của bạn một lần. Trình duyệt này miễn phí để tạo một trình nạp lớp applet mới và tải lại applet của bạn trên mỗi lần làm mới, do đó gọi các trình khởi tạo tĩnh mỗi lần. Ngay cả khi trong thực tế nó không làm điều đó, bạn không nên dựa vào initializers tĩnh được gọi chỉ một lần như một cách để đồng bộ hóa giữa các trường hợp applet. Điều gì sẽ xảy ra nếu, ví dụ, bạn đã tải cùng một applet trên cùng một máy tính cùng một lúc trong hai trình duyệt khác nhau, Firefox và Chrome? –

+0

Biến tĩnh được JVM khởi tạo, tại thời điểm lớp được nạp. Tôi không mong đợi vấn đề với classloader trong SO-câu hỏi này, vì vậy tôi chuyển sang thảo luận về JVM. Nếu người dùng bắt đầu 2 trình duyệt khác nhau - mỗi trình duyệt bắt đầu JVM riêng của mình.Cũng có thể bắt đầu JVM mới nếu applet yêu cầu JRE cụ thể hoặc các tham số JRE cụ thể (điều kiện này là OK cho câu hỏi hiện tại, vì chúng ta thảo luận một applet, vì vậy các yêu cầu và thông số JRE sẽ giống nhau). Vì vậy, biến tĩnh được chia sẻ sẽ hoạt động trong trường hợp một trình duyệt và vấn đề từ câu hỏi sẽ xuất hiện trong trường hợp của một số trình duyệt. –

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