簡體   English   中英

如何在運行時間過長時終止Matcher.find()?

[英]How to terminate Matcher.find(), when its running too long?

想知道終止長時間運行的正則表達式匹配的技術(java matcher.find()方法)。 也許子類化Matcher並添加一些邏輯以在x次迭代后終止?

基本上我是使用遺傳算法生成正則表達式,所以我沒有很多控制它們。 然后我針對某些文本測試每個文本以查看它們是否與文本的某個目標區域匹配。

因為我有點隨機生成這些正則表達式,我得到了一些瘋狂的東西,它吃了大量的cpu和一些find()調用需要一段時間來終止。 我寧願在一段時間后殺死它們,但不確定最好的方法。

如果有人有想法,請告訴我。

有一個解決方案在這里這將解決您的問題。 (那個問題與你的問題相同。)

本質上,它是一個可以注意到線程中斷的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();
    }
}

用這個包裹你的字符串,你可以打斷線程。

只是展示其他解決方案

您可以使用對輸入不敏感的NFA算法,並且比Java標准庫快數百倍。

我認為對輸入的敏感性是導致問題的原因。

你可以在這里查看介紹: 正則表達式匹配可以簡單快速(但在Java,Perl,PHP,Python,Ruby等方面很慢)

我在這里也回答了一個類似的問題: 取消長期運行的正則表達式匹配?

最糟糕的情況是可能讓人們對我大喊大叫的情況是:

你可以在另一個線程中運行正則表達式匹配,如果它運行的時間太長,你可以使用thread.stop()它。

一個可能的解決方案,它有一個很好的事情,它不會阻止主線程,將在一個單獨的線程中產生“匹配”。 您可以創建一個自定義的Callable ,它在持續時間/閾值到期后返回null ,如果成功則返回“匹配”結果。

你需要使用另一個線程,並在它用完時停止它。

有兩種停止方式:Thread#stop()和Thread#interrupt()。

使用Thread.stop()是相當危險的,並且Matcher不響應Thread.interrupt(回答中斷是一種選擇加入行為)。

但是有一個非常聰明的解決方案,一些細節在這里 使用提供的InterruptibleCharSequence(它包裝你的字符串並且幾乎像一個工作,但它增加了對Thread#interrupt()的支持),然后構建你自己的Callable返回任何匹配器返回。 現在可以使用FutureTask / ThreadPool組合執行每個runnable,您可以獲得所需的任何超時結果:

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

如果您在Java EE環境中,可以跳過復雜的部分,只需使用InterruptipleCharSequence和@Asynchronous調用。

如果這聽起來很神秘,請詢問詳細信息。

如果我是你,我會創建自己的類,我將放在我的應用程序和你用來匹配的庫之間,並實現你需要殺死線程的“中斷”方法,並以這種方式管理匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM