1

過度のリソース使用を監視したいスレッド プール (エグゼキューター) があります (CPU とメモリが非常に難しくなるように見えるため)。OS プロセスを強制終了するように、実行時間が長すぎるスレッドを「強制終了」したいと考えています。ワーカーはほとんどの時間を計算に費やしますが、I/O、主にデータベースの待機にもかなりの時間が費やされます...

Java でスレッドを停止する方法と、リソースのクリーンアップの理由 (ロックを適切に解放しない、ソケットやファイルを閉じるなど) でスレッドが非推奨になっている方法について調べてきました。推奨される方法は、ワーカー スレッドを停止して終了する必要があるかどうかを定期的に確認することです。これは明らかに、クライアント スレッドが特定の方法で記述され、一部の外部 I/O を待ってブロックされないことを想定しています。ジョブを実行できる可能性のある ThreadDeth と InterruptedException もありますが、実際には、不適切/悪意を持って記述されたワーカー スレッドで回避される可能性があり、また、(まだテストはしていませんが) 一部のスレッドでは InterruptedException が適切に機能しない可能性があるという印象を受けました (ワーカー スレッドが I/O を待機している場合。

これを緩和するもう 1 つの方法は、複数の OS プロセスを使用してシステムの一部を分離することですが、リソース消費が不要に増加します。

それにより、5年以上前の分離株やMVMに関する古い話にたどり着きましたが、おそらくJava 8または9では、その面では何も起こっていないようです...

それで、実際には、これらすべてが、それぞれが独自のクラスローダーを持つスレッドを使用することで、プロセスの貧弱なシミュレーションを実現できるかどうか迷っています。各スレッド (またはグループ) が独自のクラスローダーにロードされる場合、それを使用してプロセスをシミュレートできますか? リソース消費がどれだけ増加するかはわかりません (コード共有はあまりなく、コードは小さくないため)。少なくともプロセス コピー オン ライト セマンティクスにより、コード共有が可能になります。

推奨事項/アイデアはありますか?

編集:

これに対する一般的な関心と、これに対する解決策がこれまで JVM に存在しないというある種の失望のために質問しています (つまり、共有アプリケーション サーバーは実際には不可能です。.NET のアプリケーション ドメインまたはそのようなものは、まさにこの種に対応しているようです)。問題の)。プロセスを強制終了しても、すべてのシステム状態が初期状態に戻る保証はないことは理解していますが、少なくともハンドル、メモリ、CPU などのすべてのリソースは解放されます。クラスローダーを使用することを考えていましスレッドが保持しているロックを解放するのに役立ちます。これは、Thread.stop が推奨されない理由の 1 つです。私の現在の状況では、他に解放する必要があるのは(現在考えられる)データベース接続だけであり、必要に応じて(ウォッチドッグスレッドによって)個別に/外部で処理できます..実行可能であること、私は非推奨の方法を使用するのが嫌いです..

また、これを不適切なプロセスのセーフティネットと考えています。理想的には、プロセスは適切に動作し、非常に高度に制御されている必要があります。

したがって、明確にするために、たとえばサーバー側のJavaの人々がランナウェイスレッドをどのように処理するのかを尋ねていますか? クラスター内の多くのマシンを使用して問題を相殺し、動作の悪いマシンを再起動することで、少なくともアプリケーションがステートレスであると思われます..

4

1 に答える 1

1

スレッドとプロセスの違いは、スレッドがソケットやファイルなどのメモリとリソースを暗黙的に共有することです (スレッド ローカル メモリを回避策にします)。プロセスには暗黙的にプライベート メモリとリソースがあります。

スレッドを強制終了することは問題ではありません。問題は、動作の悪いスレッドや、妥当な動作のスレッドでさえ、リソースが一貫性のない状態のままになる可能性があることです。クラスローダーを使用しても、これを追跡したり、問題を解決したりするのに役立ちません。プロセスの場合、ほとんどのリソースが分離されているため、プロセスが使用しているリソースを簡単に追跡できます。プロセスであっても、強制終了すると、ロック、一時ファイル、および共有 IPC リソースが正しくない状態のままになる可能性があります。

本当の解決策は、適切に動作するコードを作成して、管理および回避できるようにすることです。動作の悪いコードをすべて処理しようとすることはほとんど不可能です。使用しなければならない悪いサードパーティのライブラリがある場合は、それを強制終了してクリーンアップすることを試みることができ、問題のない解決策を思い付くことができますが、クリーンなものになることは期待できません。


編集: これは、バグがあるために 2 つのプロセスまたはマシン間でデッドロックが発生する単純なプログラムです。デッドロックを止める方法は、コードを修正することです。

public static void main(String... args) throws IOException {
    switch(args.length) {
        case 1: {
            // server
            ServerSocket ss = new ServerSocket(Integer.parseInt(args[0]));
            Socket s = ss.accept();
            ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
            ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
            // will deadlock before it gets here
            break;
        }
        case 2: {
            Socket s = new Socket(args[0], Integer.parseInt(args[1]));
            ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
            ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
            // will deadlock before it gets here
            break;
        }
        default:
            System.err.println("Must provide either a port as server or hostname port as client");
    }
}
于 2012-03-18T21:30:04.963 に答える