0

タイトルについて申し訳ありませんが、質問をタイトルに入れる方法が本当にわかりません。誰かがそれをもっとうまく言えたら、それを修正してください!

とにかく、私のプログラムには2つのスレッドがあります.1つはメインプログラムであり、GUIを実行し、ユーザーに関係するすべてを実行します.作成されると、Webサイトをチェックして更新が利用可能かどうかを確認するためだけに役立つスレッドが作成されます.プログラムが使用する SQLite データベースに、JSON で情報を引き出し、挿入クエリでデータベースを更新する必要があります (これは明らかに、ユーザーがデータベースの更新中にデータにアクセスしない)。これで問題ありません。

ただし、プログラムが閉じられてメイン クラスが終了すると、更新スレッドもできるだけ早く停止する必要があります。スレッドを中断し、データベースが開いている場合は閉じる必要があると思いますが、メインスレッドが終了するとすぐにトリガーするにはどうすればよいですか? ループを使用しないため、スレッド1が生きているかどうかを確認できません...

アップデーターからこれまでのところ重要なコードは次のとおりです。

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 を閉じると、ほとんどの場合、すべてのクリーニングが完了したにプログラムが InterruptedException を出すようです。いくつかのデバッグ ステートメントでこれを証明し、エラーを送信しているデバッグ ファイルがそれを選択していないことも証明しました。アップ (つまり、プログラムは完全に閉じられます) であり、例外のスタック トレースは、私のコードやそのことについて何も話しません:

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 は実際にはコード内で呼び出されることはないため、別のものでなければなりません...

4

2 に答える 2

1

最も簡単な方法は、開始する前にデーモンスレッドを作成することですAutomaticUpdater

AutomaticUpdater au = new AutomaticUpdater();
au.setDaemon(true);
au.start();

スレッドをデーモンスレッドに設定すると、プログラム内のすべてのユーザー レベル スレッドが終了した直後にスレッドが終了します。メインはユーザーレベルのスレッドであるため、プログラムで実行している唯一のユーザーレベルのスレッドである場合、これは機能するはずです。通知を受け取ることはなく、アップデータ スレッドは黙って終了します (それがあなたの望みだと思います)。

2 番目のオプションは、ブール値をコードのどこかに配置して、アップデータ スレッドにいつ停止するかを伝えることです。アップデーターの 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));
}

編集

これはすべて、データベース アクセスのために呼び出すライブラリが独自のユーザー レベル スレッドを実行しないことを前提としています。その場合、これらのソリューションのいずれかが機能するには、コードのどこかでそれらのスレッドを明示的に停止する必要があります。

于 2013-02-18T17:25:16.783 に答える
0

あなたがすべき:

  1. 独自の定期的なプロセッサをローリングするのではなく、スケジュールされた executor、またはtimer、またはQuartzを使用することを検討してください。スケジュールされたサービスを使用して を呼び出すことができshutdownNow、タイマー タスクを使用cancelして現在および将来のジョブの停止を試みることができます。

現在の設計に固執する場合は、次のことを行う必要があります。

  1. アップデーターで明示的なシャットダウン メソッドを設計し、アプリを終了する前にメイン スレッドから呼び出します。
  2. Runnable拡張するのではなく、実装するThread
于 2013-02-18T17:27:13.757 に答える