Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将线程生命周期安全地连接在一起,包括SQLite_Java_Multithreading_Sqlite_Termination - Fatal编程技术网

Java 如何将线程生命周期安全地连接在一起,包括SQLite

Java 如何将线程生命周期安全地连接在一起,包括SQLite,java,multithreading,sqlite,termination,Java,Multithreading,Sqlite,Termination,对不起,关于标题我真的不知道如何把这个问题变成一个标题,如果有人能把它写得更好,请更正它 总之,在我的程序中,我有两个线程,一个是主程序,运行GUI和与用户有关的所有操作,当它被创建时,它会创建一个线程,仅用于检查网站,查看程序使用的SQLite数据库是否有任何更新,如果有,它将以JSON格式提取信息,然后必须使用insert查询更新数据库(这显然是通过围绕数据库解析器的同步方法完成的,以确保用户在更新数据库时不会访问数据)。这一切都很好 但是,当程序关闭且主类终止时,更新线程也必须尽快停止,但

对不起,关于标题我真的不知道如何把这个问题变成一个标题,如果有人能把它写得更好,请更正它

总之,在我的程序中,我有两个线程,一个是主程序,运行GUI和与用户有关的所有操作,当它被创建时,它会创建一个线程,仅用于检查网站,查看程序使用的SQLite数据库是否有任何更新,如果有,它将以JSON格式提取信息,然后必须使用insert查询更新数据库(这显然是通过围绕数据库解析器的同步方法完成的,以确保用户在更新数据库时不会访问数据)。这一切都很好

但是,当程序关闭且主类终止时,更新线程也必须尽快停止,但是它可能需要停止与数据库的交互并关闭数据库,以及中断自身。我想如果数据库被打开,我需要中断线程并关闭数据库,但是如何在主线程死后立即触发它呢?它不使用循环,所以我无法检查thread1是否处于活动状态

以下是迄今为止更新程序的重要代码:

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
    ,因为这是内置的功能(约定)。我查看了守护程序,唯一的问题是数据库应该关闭,据我所知,守护程序线程只是删除所有内容并终止,让数据库保持打开?至于第二个选项,我也考虑过,但它仍然意味着当前进程(可能是需要插入的大量数据,手动更新程序中的每个进程代表一个更新文件)在线程结束和程序真正消亡之前运行