1

编辑
当前代码是有效的解决方案,它不会阻止应用程序,它包含在批准的答案中提出的建议。


我想要一个后台线程连续下载 MS Access 数据库,而我的 tomcat 7 Web 应用程序正在运行,该线程确实下载了数据库,但是它似乎阻止了我的应用程序的启动,因为我无法从该服务访问任何页面,这是我正在使用的代码:

public class DatabaseUpdater implements ServletContextListener {
    private Thread thread = null;

    private final Runnable updater = new Runnable() {

        private boolean hasExpired(File mdbFile) throws IOException {
            if (!mdbFile.exists())
                return true;

            Long ttl = Long.parseLong(Configuration.getValueForOS("db.http-expiration"));

            Date now = new Date();
            Date fileDate = new Date(mdbFile.lastModified());

            return (now.getTime() - fileDate.getTime()) > ttl;
        }

        @Override
        public void run() {
            while (true) {
                if (Thread.currentThread().isInterrupted())
                    throw new RuntimeException("Application Shutdown");

                try {
                    String databases[] = new String[]{"database1", "database2"};
                    for (String database : databases) {

                        String fileName = database + "." + StringUtil.randomString(8) + ".mdb";
                        String fileLocation = Configuration.getValueForOS("db.path");

                        File mdbFile = new File(fileLocation, fileName);
                        File currentDatabaseFile = new File(fileLocation, database + ".mdb");

                        if (hasExpired(currentDatabaseFile)) {
                            URL url = new URL(Configuration.getValueForOS("db.url." + database));
                            InputStream in = url.openConnection().getInputStream();
                            OutputStream out = new FileOutputStream(mdbFile);

                            FileUtil.streamBridge(in, out);
                            FileUtil.close(in, out);

                            while (currentDatabaseFile.exists() && !currentDatabaseFile.delete()) ;
                            while (!mdbFile.renameTo(currentDatabaseFile)) ;
                       }
                   }
                     // Put the thread to sleep so the other threads do not starve
                    Thread.sleep(Long.parseLong(
                        Configuration.getValueForOS("db.http-expiration"));
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                } catch (InterruptedException ie) {
                    ie.printStackTrace();
                }
            }
        }
    };

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        this.thread = new Thread(updater);
        thread.start();
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        if (this.thread.isAlive())
            this.thread.interrupt();
    }
}

可能是什么原因造成的?

我的实现基于这个问题:Background Thread for a Tomcat servlet app

4

1 回答 1

1

鉴于您的代码永远循环,您可能会饿死 VM 中的所有其他线程。尝试不时休眠线程。

于 2012-12-21T22:08:05.343 回答