Java applet:如何在页面刷新之前确保销毁完成

时间:2012-04-09 19:13:03

标签: java applet logging handler java.util.logging

在Java util日志中,我在init()上启动处理程序,并在destroy()处关闭处理程序,它完全正常:创建了一个日志文件等。如果用户正常刷新页面,它仍然只是创建一个日志文件。

但是如果用户使用applet快速刷新页面几次,看起来似乎没有调用destroy()或者没有完成任务,并且因为init()再次被调用,它假定上一个文件仍然被锁定并创建一个新的日志文件。

我尝试使用destroy()和finalize()来关闭处理程序,但它不起作用。 任何人都知道如何解决这个问题?

另一个小问题是:如果init()尚未完成并且页面被刷新,实际发生了什么。它是否会继续这个过程并最终导致调用destroy()或它是否只是停在那里?

3 个答案:

答案 0 :(得分:4)

引自Java Tutorials

  

Java Plug-in软件为每个Java创建一个工作线程   小程序。

在多线程环境中,您应该非常小心共享资源。最好和最简单的方法是不要共享任何东西(最好的扩展,没有死锁)。

我假设您每次在“init”-method中初始化您的处理程序。如果是,则应使用一个静态共享记录器(请检查此link)。它将有助于改善情况,但如果您使用applet启动多个浏览器 - 仍将创建新的日志文件。并且Oracle不推荐这种解决方法,并为了向后兼容而保留。


推荐且易于实施的解决方案 - “每个applet都应拥有自己的记录器并写入自己的文件”。日志文件名生成代码:

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

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

另外,Best Practices For Applet Development


回答您的小问题(已更改):

根据java插件中对此old bug的讨论,applet可以随时以一些预定义的间隔进行清理。因此,您应该将资源清理代码放在“停止”或“销毁”方法中,但您不应该依赖该代码执行的内容。

  

Applet生命周期由浏览器控制,applet不应该   给予在其托管文档被销毁时运行的功能   浏览器。

     

自6u10以来,旧插件和新插件都强制实施applet关闭   经过一段固定的时间(旧插件1000毫秒,新插件200毫秒)   插件)让applet停止。

答案 1 :(得分:0)

希望你没有在FF测试。在这里阅读: https://bugzilla.mozilla.org/show_bug.cgi?id=638070

答案 2 :(得分:0)

您只是遇到了多线程环境的基本限制。

你真的无法判断何时会相对于其他线程调用destroy()finalize()。当浏览器重新加载页面时,它可能会在新线程中加载applet。如果用户快速重新加载两次,它可能会创建2个新线程,在第二个线程上调用init()(用户实际看到的线程),然后在用户从未看到的线程上调用init()之前调用{前一个{1}}。在生命周期的另一端,垃圾收集线程可能在不再需要该对象后很长时间调用destroy()。您正在多线程环境中工作,并且您不能指望线程之间的任何操作顺序。

引用Javadoc:

  

applet是一个小程序,不打算单独运行,而是嵌入到另一个应用程序中。

如果您只有一个日志文件,那么外部应用程序应该控制创建/打开和关闭日志。 如果外部应用程序是Web浏览器,则无法解决您遇到的问题。然后,如果您在Web浏览器中运行applet,则不应将日志写入文件系统。这通常是不礼貌的行为。

如果您必须在Web浏览器中拥有applet的日志文件,最简单的解决方案是每次调用finalize()以创建特定于该applet调用的新文件。如果你想要雄心勃勃,你可以使用锁定文件来指示哪些文件正在使用中,并在init()时将未锁定的日志文件连接成一个更大的文件,但是再次遇到协调跨线程的连接过程的问题。