18

私はJavaバイトコードの例をたくさん持っていますが、それらはすべてClojureから実行したいと思います。バイトコードの各シーケンスには無限ループが含まれている可能性があります。その場合、数秒後に実行を停止します。私はこれを行う手段として先物を見てきました。いくつかの実装を探し回ったので、次の両方のコードを試しました。

(deref (future (loop[a 1] (recur a)) :done!) 1000 :impatient!)

...またhttps://gist.github.com/3124000のコード

どちらの場合も、ループは適切にタイムアウトしているように見えます(後者の場合、将来は完了してキャンセルされたと報告されています)が、CPU使用率が99%前後に上昇し、そこにとどまっています。また、このコードを実行するたびに、Javaプロセスが余分なスレッドを取得することもわかります。

将来はキャンセルされているように見えますが、コードはまだ実行されています。私のプログラムでは、いくつかの非常にタイトな無限ループ(たとえば、「20 PRINT GOTO 10」に相当するJavaバイトコード)を実行してタイムアウトする必要があり、実行しているコードを変更するオプションがありません。

私がこの振る舞いを見ている理由についての考え。それを防ぐために私ができること。または、そのようなコードを実行してタイムアウトするという私の目的を実現するための代替方法はありますか?

4

3 に答える 3

8

Javaでサポートされているスレッドキャンセルのメカニズムは割り込みです。この.stop()メソッドは、理由により非推奨になりました。ドキュメント、Effective Java、 JavaConcurrencyinPracticeなどを参照してください。

実際、FutureTask(これを支持するfuture-cancel)の実装は割り込みベースです。

send-off今日の時点で、Clojureの各未来は、(アクションと同じように)無制限のスレッドプールによって支えられています。したがって、スレッド中断プリミティブを活用できます。

(def worker
  (let [p (promise)]
    {:future (future
               (let [t (Thread/currentThread)]
                 (deliver p t)
                 (while (not (Thread/interrupted))
                   (println 42)
                   (Thread/sleep 400))))
     :thread @p}))

これで、またはのいずれかを正常に実行でき(.interrupt (:thread worker))ます(future-cancel (:future worker))

これはスレッドキャンセルメカニズムをFuturesのメカニズムに結合しますが、利用可能なExecutor実装は、前のタスクが設定された可能性のある中断ステータスをクリアするのに十分スマートであるため、あるタスクへの中断が他のタスクに影響を与えることはありません。同じスレッド。

重要なのは、スレッドを先制的に強制終了することは一般的に悪い考えです。タスクをキャンセルしたい場合は、何らかの方法で明示的にキャンセルできるようにする必要があります。OTOH、あなたの特定のケースでは、不透明なバイトコードを実行しているので、に頼る以外に選択肢はありません.stop()

于 2013-01-26T19:46:56.870 に答える
4

スレッド内で実行されているコードを実際に強制終了する唯一の方法は、非推奨の.stopメソッドを使用することです。多くの場合、非推奨になる理由はそれほど重要ではありません。

私はそれをするためにclojailに機能を持っていました。関数をスナッチアウトするか、ライブラリをプルするだけです。

于 2012-07-17T10:37:49.370 に答える
1

Java APIドキュメントによるとcancel、タスクをすぐに停止できることは許可されていません。

このタスクの実行をキャンセルしようとします。タスクがすでに完了している場合、すでにキャンセルされている場合、またはその他の理由でキャンセルできなかった場合、この試行は失敗します。成功し、cancelが呼び出されたときにこのタスクが開始されていない場合、このタスクは実行されません。タスクがすでに開始されている場合、mayInterruptIfRunningパラメーターは、タスクを停止するためにこのタスクを実行しているスレッドを中断する必要があるかどうかを決定します。

于 2012-07-17T11:19:31.283 に答える