12

Javaを使用して(アカデミック)ソフトウェアを開発したとき、実装がかなり悪いAPIを使用せざるを得ませんでした。これは、特定の入力データのセットに対するこのAPIの呼び出しが、返されない場合があることを意味します。提供されたアルゴリズムは決定論的なものであり、データセットで終了することもあれば、同じデータセットで無限ループに陥ることもあるため、これはソフトウェアのバグであったに違いありません...

ただし、APIの修正または再実装は、単に範囲を超えていました。私もソースを持っていましたが、APIは、文書化されておらず、ソースがなく、Webから消えてしまった(または存在しなかった)他のAPIに大きく依存していました。一方、この「悪い」APIは、私が抱えていた特定の問題を解決した唯一のAPIだったので、私は本当にそれに固執しなければなりませんでした。

問題は、それを動作させるAPIを処理する最もクリーンな方法は何ですか?この問題に直面したとき、APIへの呼び出しを別のスレッドに入れることにしました。次に、別のスレッドが、このスレッドが終了したかどうかをときどきチェックします。一定の時間が経過したら、を使用して処理スレッドをThread#stop()強制終了し、次回に戻ることを期待して処理を再開します。今、私はこのメソッドが非推奨であり、使用してはならないことを知っています(そして当時は知っていました)。しかし、この学術的な文脈では、ソフトウェアがクラッシュするのではなく、未定義の状態になる可能性があることは許容されていました。

また、無限ループに陥った処理スレッドを無視することもできませんでした。これは、CPUを大量に消費する操作を実行して、ユーザーのマシンの速度を大幅に低下させるためです。

私が試しなかったもう1つの方法は、スレッドではなく別のプロセスで処理を開始することです。これは、ソフトウェアを不整合な状態にすることなく、サブプロセスを完全に強制終了できるためです。または、新しいSwingWorkerクラス(まだ利用できませんでした)がその仕事をしたでしょうか?方法はcancel()ありますが、ドキュメントには「このタスクの実行をキャンセルしようとしている」と書かれているため、信頼できるアプローチのようにも見えません。

4

4 に答える 4

11

別のプロセスを使用することをお勧めします。2番目のスレッドが中断されているかどうかを定期的にチェックしない限り、Javaで1つのスレッドが2番目のスレッドを強制終了する安全な方法は基本的にありません。

理想的な解決策は、分離株を使用することです。分離は、本質的に、Javaアプリが作成、管理、および通信できるプライベート仮想マシンです。特に、親アプリは分離株とそのすべてのスレッドを安全に強制終了できます。

参照:JSR-000121アプリケーション分離API仕様-最終リリース

問題は、IsolatesをサポートするJVMを見つけることです。

于 2009-08-02T12:28:40.607 に答える
5

私は、この種の個別のプロセスの大ファンです。

サブプロセスを生成し、結果を待ちます。

API が非決定論的である場合は、タイマー スレッドをラッパーに配置して、不正な API をメイン プログラムに組み込みます。

そうすれば、サブプロセスは常に指定された時間内に終了します。有用な結果を生成するか、失敗を示すシステム終了コードを生成します。

于 2009-08-02T12:31:14.180 に答える
2

@S.Lott と @Stephen C の両方の回答は、この種の状況を処理する方法に関して適切ですが、非学術環境でそれを追加したいと思います.実用的なように。通常、他の理由で提供されたソリューションを選択することによって、不適切な API に閉じ込められた状況では、時間をかけて機能を独自のものに置き換えることに取り組んできました。顧客は、ソフトウェアを評価するだけでなく、実際に使用する (または使用しない!) 必要があるため、教授ほど寛容ではありません。

ダクトテープを使用することが問題を解決するのに適切な選択肢である場合は確かにあります. ただし、説明したように動作が悪い場合は、あまり長く依存せず、実際の修復に取り掛かることをお勧めします。

于 2009-08-02T12:43:32.653 に答える
1

最善の方法は、問題の API を再実装することです。ただし、あなたが言うように、それは非常に重量があり、おそらく範囲外のソリューションです。

次善の策は、可能であれば API をラップすることです。基本的に、失敗の原因となっているデータセットが何であるかを事前に判断できれば、決定性を保証するために呼び出しを拒否できます。同じデータセットで呼び出しを繰り返すと、以前の呼び出しで無限にループしたときに終了することがあると示唆しているため、これもうまくいくとは思えません。

上記のオプションが利用できない場合:現在のスレッド ソリューション、悪い選択肢の中で最良のもの
だと思います。メソッド呼び出しのためにプロセスをスピンアップすることは、スレッドを使用するよりも安全であるとしても、パフォーマンスの観点からは許容できないほど重すぎるようです。 Thread.stop()は非常に危険ですが、ロックを完全に防止すれば回避できます。

于 2009-08-02T12:35:05.570 に答える