Javaコマンドラインアプリケーションがリソースを占有することなくバックグラウンド作業を行うための適切な方法は何ですか? ループで sleep() を使用する必要がありますか、それともよりエレガントで効率的な方法がありますか?
4 に答える
いくつかのヒューリスティック:
- アプリケーションでスケジュールを決定しようとしないでください。オペレーティング システムのスケジューラは、あなたのスケジューラよりもはるかに優れています。その仕事をさせてください。
- 必要がなければ投票しないでください。たとえば、n秒間スリープしてから、ブロックされていないソケットをチェックするために起動する代わりに、ソケットをブロックします。この 2 番目の戦略は、オペレーティング システムのスケジューラとうまく連携します。
- 必要がない場合は巨大なヒープを使用しないでください。また、一度に巨大なメモリのチャンクを割り当てないようにしてください。スラッシング アプリケーションは、システム パフォーマンスに悪影響を及ぼす傾向があります。
- バッファリングされた I/O を使用します。いつも。バッファリングされていない I/O が必要だと思う場合は、その考えが正しいことを確信してください。(あなたはおそらく間違っています。)
- 多くのスレッドを生成しないでください。スレッドは驚くほど高価です。特定のポイントを超えると、スレッドが増えるとアプリケーションのパフォーマンス プロファイルが低下します。同時に行う作業が多い場合は、 を学習して使用して
java.util.concurrent
ください。
もちろん、これはスターターリストに過ぎません...
行う作業がない場合にのみ、sleep() を使用します。たとえば、タスク キューを定期的にポーリングするようなことを行っていて、そこに何もない場合は、しばらくスリープしてからもう一度確認するなどです。
CPU を独り占めしないようにしたいが、まだ実際の作業を行っている場合は、定期的に Thread.yield() を呼び出すことができます。これにより、CPU の制御が放棄され、他のスレッドが実行できるようになりますが、スリープ状態になることはありません。他のプロセスが CPU を必要としない場合は、制御を取り戻して作業を続行します。
スレッドの優先度を低く設定することもできます: myThread.setPriority(Thread.MIN_PRIORITY);
Ishmael が言ったように、メイン スレッドでこれを行わないでください。代わりに「ワーカー スレッド」を作成します。そうすれば、UI (GUI または CLI) は引き続き応答します。
いくつかの方法があります。私は ExecutorService を使用します...たとえば:
ExecutorService service = Executors.newCachedThreadPool();
Callable<Result> task = new Callable<Result>() {
public Result call() throws Exception {
// code which will be run on background thread
}
};
Future<Result> future = service.submit(task);
// Next line wait until background task is complete
// without killing CPU. Of course, you can do something
// different here and check your 'future' later.
//
// Note also that future.get() may throw various exceptions too,
// you'll need to handle them properly
Result resultFromBackgroundThread = future.get();
これは Java 5 のコードで、ExecutorService、Callable、Future などがjava.util.concurrent
パッケージに含まれています。
開始する場所の 1 つは、それらのリソースのみが使用され、他のオブジェクトが使用されていないことを確認することです (これにより、ガベージ コレクションが行われます)。
シングルスレッドアプリケーションに sleep() を配置すると、現在のスレッドが停止するだけです。情報をユーザーに表示する必要がある一方で、バックグラウンドで処理されているデータを達成しようとしている場合は、バックグラウンド プロセスを別のスレッドに配置することをお勧めします。