13

'forever' を実行すると考えられるプログラムを作成する必要があります。つまり、定期的に終了することはありません。今まで、私はいつも実行して一日の終わりに終了するプログラムを書いていました。プログラムはいくつかの同期を行い、n分間一時停止してから再度同期する必要があります。

私の現在の実装に問題はないはずであり、理論的には問題なく動作するはずですが、実際の経験はありません。

では、実行時間が非常に長く、非常に堅牢でリソース効率の高い Java プログラムを作成するための「パターン」またはベスト プラクティスはありますか? たとえば、1 か月または 1 年のランタイムの後に、どのような問題が考えられるでしょうか?

いくつかの背景:

  • Java : 1.7 ですが、1.5 にコンパイルされます
  • OS:Windows(正確なバージョンは未定)

前もって感謝します

4

2 に答える 2

9

この種のアプリを作成するときに心に留めておかなければならなかったすべてのことのブレイン ダンプです。

メモリ リークを回避する

毎日正午に 1 回実行されるアプリがあり、その中にFileWriter. 私はそれを適切にクローズしていなかったので、仮想マシンが数週間後になぜメルトダウンするのか疑問に思うようになりました. メモリ リークは、実際にはあらゆる形で発生する可能性があります。最も一般的な例の 1 つは、de-reference適切にオブジェクトを作成していないことです。たとえば、クラスのフィールドを一時ストレージの方法として使用します。多くの場合、クラスは存続し、参照も存続します。これにより、オブジェクトが残り、メモリに座って何もしなくなります。

適切な種類のスケジューラを使用する

私はそのアプリで Java を使用しましたが、後で、別のアプリがシステム クロックを変更しているときにScheduledThreadPoolExecutorTimerを使用する方がよいことを知りました。したがって、完全にJavaベースのままにする予定がある場合は、この質問で説明されているすべての理由から、タイマーよりもそれを使用することを強くお勧めします.

メモリ使用量と環境に注意してください

アプリが毎日大量のデータを読み込んでいて、同じサーバーで他のアプリを実行している場合は、タイミングに注意する必要があります。たとえば、正午に 3 つのアプリがスケジュールされた操作を実行するとします。それ以外の時間に実行するのはおそらく賢明な方法です。コードを実行する環境に注意してください。

エラー処理

おそらく、何か問題が発生した場合に、アプリを壊さずに通知するようにアプリを構成する必要があります。数時間ごとの特定の時間に実行されている場合、それはおそらく人々がそれに依存していることを意味します。そのため、例外の性質を詳述する電子メールを送信する関数を Java コードに含めることができます。

構成可能にする

繰り返しになりますが、1 日のさまざまな時点で実行する必要がある場合は、コードに小さな変更を加えるために数時間もプルダウンする必要はありません。代わりに、Java プロパティ ファイル、または XML 構成 (または実際には何でも) に移植します。これの利点は、プログラムを更新して、実際に違いに気付く前に起動して実行できることです。

staticキーワードが怖い

その悪い男の子は、親参照を破棄しても、オブジェクトを存続させます。注意しないと、すべてのメモリ リークの元になります。定数については問題ありませんが、変更する必要がなく、プロジェクト内に存在する必要がないことがわかっているものは正常に実行されますが、プロジェクト内のランダムな値に使用している場合は、なぜあなたのではなく、数時間ごとにアプリがクラッシュしsyncingます。

そのことを思い出させてくれた@ X86への小道具。

于 2013-10-10T08:29:26.473 に答える
4

メモリ リークが最大の問題になる可能性があります。ロジックの反復後に保持される長期参照がないことを確認してください。永久に参照される比較的小さなオブジェクトでさえ、最終的にメモリを使い果たします(さらに悪いことに、成長率が 1GB/月の場合、テスト中に検出するのが難しくなります)。プロファイラーのスナップショット機能を使用するのが役立つ可能性があるアプローチの 1 つです。一時停止中にスナップショットを作成し、同期を数回実行してから、別のスナップショットを作成します。これらを比較すると、同期間のデルタが表示されます。これは、できればゼロである必要があります。

キャッシュのメンテナンスは別の問題です。キャッシュの全体的なサイズは厳密に制限する必要があります (一方で、表示されるすべてのものが問題を引き起こさないほど十分に小さいため、実行時間の短いプログラムではなくても済むことがよくあります)。同様に、キャッシュの無効化を適切に行うこともより重要です。大まかに言えば、キャッシュされたものはすべて、プログラムの実行中のある時点で古くなるため、これを検出して適切なアクションを実行できる必要があります。これは、キャッシュされたデータのゴールデン ソースがどこにあるかによっては注意が必要です。

最後に言及するのは、例外処理です。実行時間が短いプロセスの場合、多くの場合、例外が発生したときに単にプロセスを終了させるだけで十分です。そのため、問題を処理してアプリを再実行できます。長時間実行されるプロセスでは、おそらくこれよりも防御的である必要があります。プログラムの一部をスレッドで実行することを検討してください。スレッドは、失敗した場合に再起動*できます。スーパーバイザ タイプのモジュールが必要な場合があります。このモジュールは、他のすべてがハートビート状態であることを確認し、そうでない場合は再起動します。構造に適している場合、Java の標準のエグゼキュータよりもアクター スタイルのライブラリを使用すると、これを達成する方がはるかに簡単です。可能であれば、動作を多少変更できるフック (おそらく JMX/MBeans で公開) が必要な場合があります。プロセスを停止することなく、短期的なハック/回避策に影響を与えることができます。ただし、数か月後に何がうまくいかないかを正確に予測するには、かなりの先見性が必要です...

*というか、別のスレッドでジョブを再開できます

于 2013-10-10T08:30:51.310 に答える