8

長時間実行される正規表現の一致を終了するための手法について疑問に思っています (Java matcher.find() メソッド)。おそらくMatcherをサブクラス化し、x回の反復後に終了するロジックを追加しますか?

基本的に、遺伝的アルゴリズムを使用して正規表現を生成しているため、それらをあまり制御できません。次に、それぞれをテキストに対してテストして、テキストの特定のターゲット領域と一致するかどうかを確認します。

したがって、これらの正規表現をランダムに生成しているので、いくつかのクレイジーなことが起こっており、大量の CPU を消費し、一部の find() 呼び出しが終了するまでに時間がかかります。しばらくしてから殺したほうがいいのですが、それを行う最善の方法がわかりません。

ですから、誰かアイデアがあれば教えてください。

4

6 に答える 6

3

ここにあなたの問題を解決する解決策があります。(その質問はあなたの問題と同じです。)

基本的に、スレッドの割り込みを認識できる CharSequence です。

その答えのコード:

/**
 * CharSequence that noticed thread interrupts -- as might be necessary 
 * to recover from a loose regex on unexpected challenging input. 
 * 
 * @author gojomo
 */
public class InterruptibleCharSequence implements CharSequence {
    CharSequence inner;
    // public long counter = 0; 

    public InterruptibleCharSequence(CharSequence inner) {
        super();
        this.inner = inner;
    }

    public char charAt(int index) {
        if (Thread.interrupted()) { // clears flag if set
            throw new RuntimeException(new InterruptedException());
        }
        // counter++;
        return inner.charAt(index);
    }

    public int length() {
        return inner.length();
    }

    public CharSequence subSequence(int start, int end) {
        return new InterruptibleCharSequence(inner.subSequence(start, end));
    }

    @Override
    public String toString() {
        return inner.toString();
    }
}

これで文字列をラップすると、スレッドを中断できます。

于 2011-08-19T19:49:33.223 に答える
1

最悪のシナリオと、人々が私に怒鳴る可能性のあるシナリオは次のとおりです。

別のスレッドで正規表現マッチングを実行できます。実行時間が長すぎる場合は実行できますthread.stop()

于 2011-08-19T18:28:47.397 に答える
1

別の解決策を示すだけです。

入力に敏感ではなく、Java 標準ライブラリより数百倍高速な NFA アルゴリズムを使用できます。

入力に対する感度が問題を引き起こす元の理由だと思います。

ここで紹介を確認できます:正規表現マッチングはシンプルで高速です (ただし、Java、Perl、PHP、Python、Ruby などでは低速です)。

私は同様の質問にも答えました: Canceling a long running regex match?

于 2016-02-15T09:48:10.947 に答える
0

メインスレッドをブロックしないという良い点がある1つの可能な解決策は、別のスレッドで「一致」を生成することです。期間/しきい値の期限が切れた後、または成功した場合は「一致」の結果Callableを返すカスタマイズを作成できます。null

于 2011-08-19T18:27:54.190 に答える
0

別のスレッドを使用し、時間切れになったら停止する必要があります。

停止には、Thread#stop() と Thread#interrupt() の 2 つの方法があります。

Thread.stop() の使用はかなり危険であり、Matcher は Thread.interrupt に応答しません (割り込みへの応答はオプトイン動作です)。

しかし、本当に賢い解決策があります。詳細はこちらです。提供された InterruptibleCharSequence を使用して (それはあなたの文字列をラップし、ほとんど同じように動作しますが、Thread#interrupt() のサポートを追加します)、マッチャーが返すものを返す独自の Callable を構築します。各ランナブルは、FutureTask / ThreadPool コンボを使用して実行できるようになり、任意のタイムアウトで結果を取得できます。

Boolean result = myMatchingTask().get(2, TimeUnit.SECONDS)

Java EE 環境を使用している場合は、複雑な部分をスキップして、InterruptipleCharSequence と @Asynchronous 呼び出しを使用できます。

これが不可解に聞こえる場合は、詳細を尋ねてください。

于 2011-08-19T19:56:51.823 に答える
-1

もし私があなたなら、自分のアプリケーションとマッチングに使用しているライブラリの間に配置する独自のクラスを作成し、スレッドを強制終了するために必要な「割り込み」などのメソッドを実装し、その方法でマッチングを管理します。

于 2011-08-19T19:39:38.770 に答える