Java 如何将线程生命周期安全地连接在一起,包括SQLite
对不起,关于标题我真的不知道如何把这个问题变成一个标题,如果有人能把它写得更好,请更正它 总之,在我的程序中,我有两个线程,一个是主程序,运行GUI和与用户有关的所有操作,当它被创建时,它会创建一个线程,仅用于检查网站,查看程序使用的SQLite数据库是否有任何更新,如果有,它将以JSON格式提取信息,然后必须使用insert查询更新数据库(这显然是通过围绕数据库解析器的同步方法完成的,以确保用户在更新数据库时不会访问数据)。这一切都很好 但是,当程序关闭且主类终止时,更新线程也必须尽快停止,但是它可能需要停止与数据库的交互并关闭数据库,以及中断自身。我想如果数据库被打开,我需要中断线程并关闭数据库,但是如何在主线程死后立即触发它呢?它不使用循环,所以我无法检查thread1是否处于活动状态 以下是迄今为止更新程序的重要代码:Java 如何将线程生命周期安全地连接在一起,包括SQLite,java,multithreading,sqlite,termination,Java,Multithreading,Sqlite,Termination,对不起,关于标题我真的不知道如何把这个问题变成一个标题,如果有人能把它写得更好,请更正它 总之,在我的程序中,我有两个线程,一个是主程序,运行GUI和与用户有关的所有操作,当它被创建时,它会创建一个线程,仅用于检查网站,查看程序使用的SQLite数据库是否有任何更新,如果有,它将以JSON格式提取信息,然后必须使用insert查询更新数据库(这显然是通过围绕数据库解析器的同步方法完成的,以确保用户在更新数据库时不会访问数据)。这一切都很好 但是,当程序关闭且主类终止时,更新线程也必须尽快停止,但
public static class AutomaticUpdater extends Thread
{
DictionaryGUI pGUI;
DatabaseParser pParser;
public void run()
{
Updater pUpdater = new Updater (pParser, pGUI, true); //the manual updater is used to process the data
for (String sURL : getURLs()) //getURLS() returns areas in the website that contain relevant data
{
pUpdater.process(getData(sURL)); //create the INSERT statements and send to database
}
}
}
那么,当主线程死亡时,如何确保更新程序死亡?被JVM杀死的线程是否抛出异常或进行任何类型的清理函数调用,我可以覆盖这些调用以杀死更新程序并关闭数据库
编辑:好的,我已经找到了解决方案,但我仍然愿意接受更好的想法
这将附加到GUI的JFrame:
private class ProgramCleaner implements WindowListener
{
public void windowClosing(WindowEvent e)
{
MainLauncher.pAutoUpdater.kill();
}
public void windowActivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
}
其中kill中断更新程序并确保数据库关闭:D
编辑2:似乎当GUI关闭时,程序几乎总是在所有清理工作完成后发出中断异常,我用一些调试语句证明了这一点,并且我发送错误到的调试文件没有拾取它(即程序完全关闭)异常的堆栈跟踪从不谈论我的代码或其他相关内容:
Exception while removing reference: java.lang.InterruptedException
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
at sun.java2d.Disposer.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
有人知道为什么会这样吗?wait在我的代码中从来没有真正被调用过,所以它必须是其他的东西…最简单的方法是在启动之前将您的
AutomaticUpdater
设置为一个deamon线程:
AutomaticUpdater au = new AutomaticUpdater();
au.setDaemon(true);
au.start();
将线程设置为deamon线程意味着它将在程序中的所有用户级线程终止后立即终止。Main是一个用户级线程,因此如果它是程序中运行的唯一用户级线程,那么它应该可以工作。你将不会收到任何通知,你的更新程序线程将悄无声息地死去(我假设这就是你想要的)
第二种选择是在代码中的某个地方放一个布尔值,告诉更新程序线程何时停止。您可以在更新程序的for循环中检查该布尔值,并在布尔值切换为false时让它立即返回
boolean running = true; //somewhere near the top of your class
...
//main launches the updater thread here
...
//inside updater's run() method:
for (String sURL : getURLs()){
if(!running) return;
pUpdater.process(getData(sURL));
}
编辑
这一切都假设您调用数据库访问的库不运行它们自己的用户级线程。如果是这样,那么您需要在代码中的某个位置显式停止这些线程,以使这些解决方案中的任何一个正常工作。您应该:
shutdownNow
,使用计时器任务,您可以调用cancel
尝试停止当前和未来的作业Runnable
,而不是扩展Thread
在第二个选项中,我建议使用
interrupted()
而不是boolean running
,因为这是内置的功能(约定)。我查看了守护程序,唯一的问题是数据库应该关闭,据我所知,守护程序线程只是删除所有内容并终止,让数据库保持打开?至于第二个选项,我也考虑过,但它仍然意味着当前进程(可能是需要插入的大量数据,手动更新程序中的每个进程代表一个更新文件)在线程结束和程序真正消亡之前运行