如何对运行正则表达式的java函数设置时间限制
我在java函数中运行一个正则表达式来解析一个文档,如果它找到了正则表达式指定的字符串,则返回true;如果没有找到,则返回false。但问题是,当文档不包含正则表达式指定的字符串时,返回false需要很长时间,如果执行该函数需要6秒以上,我希望终止该函数 如何设置该功能的6秒时限,以便在超过6秒时强制终止该功能 我正在从类1调用类2的方法“方法1”。“方法1”调用同一类的“方法2”,即“类2”。方法2在文档上运行正则表达式代码。如果它找到正则表达式指定的字符串,那么它将结果返回给方法1,方法1将结果返回给“类1”中的方法,该方法调用类2的“方法1”。 现在的问题是类2的method1和method2的执行时间都不应该超过6秒 因此,我在同一个文件中创建了一个新的RegexpThread类,其中包含我的class2。然后我将类2的method2移动到类RegexpThread中。然后,每当调用方法1时,它都会实例化RegexpThread类,如下所示:如何对运行正则表达式的java函数设置时间限制,java,multithreading,Java,Multithreading,我在java函数中运行一个正则表达式来解析一个文档,如果它找到了正则表达式指定的字符串,则返回true;如果没有找到,则返回false。但问题是,当文档不包含正则表达式指定的字符串时,返回false需要很长时间,如果执行该函数需要6秒以上,我希望终止该函数 如何设置该功能的6秒时限,以便在超过6秒时强制终止该功能 我正在从类1调用类2的方法“方法1”。“方法1”调用同一类的“方法2”,即“类2”。方法2在文档上运行正则表达式代码。如果它找到正则表达式指定的字符串,那么它将结果返回给方法1,方法1
RegexpThread rt = new RegexpThread() {
public void run() {
method 2(m, urlCopy, document);
}
};
rt.start();
try {
rt.join(6 * 1000);
} catch (InterruptedException e) {
return "y";
}
if(rt.getResultXml().equals("")) {
return "g";
}
resultXml.append(rt.getResultXml());
return resultXml.toString();
显示的代码在class2的方法1中。RegexpThread类中的方法2对文档执行一些正则表达式搜索。RegexpThread类中有一个名为“resultXml”的私有字段。如果方法2找到了正则表达式指定的字符串,那么它将结果分配给私有字段“resultXml”。如果不是,则“resultXml”包含其默认值,即空字符串
因此,在上面的“if块”中,它将根据空字符串检查“resultXml”字段。如果是空字符串,则表示正则表达式在文档中未找到其字符串。但如果它不是空字符串,则表示正则表达式已在文档中找到该字符串,并已将结果分配给“resultXml”字段
那么,看看这个,告诉我该怎么做…通过执行器服务启动线程并给它一个超时,如下所示:
ExecutorService pool = Executors.newFixedThreadPool(POOL_SIZE);
pool.execute(rt);
pool.awaitTermination(timeout, timeUnit);
将等待任务完成(以及此ExecutorService
下的所有其他任务),线程被中断,或出现超时(以先到为准)
听起来这很适合您的需要。您没有显示实际执行正则表达式的函数,因此我假设它从文件中读取行并在每行上执行正则表达式 如果是这种情况,那么更好的解决方案是将超时值传递给该函数。在每N行之后(不管N是什么),它检查超时值
您将遇到的真正问题是阻塞IO—例如,从网络读取。在这种情况下,您无法从Java执行任何操作,因为阻塞实际上发生在操作系统内核中。您所做的对我来说很好,下面是我如何修改它的:
final AtomicReference<String> resultXml = new AtomicReference<String>();
RegexpThread rt = new RegexpThread() {
public void run() {
method2(m, urlCopy, document, resultXml);
}
};
rt.start();
try {
rt.join(6 * 1000);
} catch (InterruptedException e) {
return "y";
}
if(resultXml.get() == null) {
rt.interupt();
return "g";
}
resultXml.append(resultXml.get());
return resultXml.toString();
final AtomicReference resultXml=new AtomicReference();
RegexpThread rt=new RegexpThread(){
公开募捐{
方法2(m、urlCopy、文档、结果XML);
}
};
rt.start();
试一试{
rt.join(6*1000);
}捕捉(中断异常e){
返回“y”;
}
if(resultXml.get()==null){
rt.interupt();
返回“g”;
}
append(resultXml.get());
返回resultXml.toString();
这里我可能弄错了,但我认为所有终止线程的方法都是正确的。推荐的方法是使用一个共享的isRunning
变量,工作线程会定期检查该变量,并在设置后正常退出
这在你的情况下不起作用,但在我看来,你在治疗症状,而不是真正的问题。您应该发布regexp函数的代码,执行该函数需要6秒钟。如果是regexp本身,那么执行时间可能是一个例子。我现在假设您的regexp代码是正确的,它实际上是一些CPU限制为6秒的计算代码 鉴于上述情况,我认为你只有一个选择。在多个阶段/迭代中执行代码,并检查变量以请求暂停。您不能使用正常的
模式
/匹配器
代码来执行此操作
您可以通过预先以某种方式分割输入字符串,然后一点一点地输入到regexp(初始分割必须独立于regexp)
您不能通过以下方式执行此操作:
Thread.stop()
等。这已被弃用,无法正常工作Thread.interrupt()
。这将在线程上设置一个中断标志,该标志仅在线程执行IO时被检查。如果线程是CPU绑定的,则永远不会检查该标志鉴于上述情况,我将再次了解为什么regexp需要6秒才能匹配。regexp正确吗?您能在较小的文本段上执行regexp吗 回答这个问题有两种方法 一方面,没有一种实用/有效的方法可以安全地终止正在执行
Matcher.find(…)
或Matcher.match(…)
的线程。调用Thread.stop()
可以工作,但存在严重的安全问题。解决这个问题的唯一方法是开发自己的正则表达式引擎,定期检查中断
标志。(这并非完全不切实际。例如,如果GPL不是您的问题,您可以从OpenJDK中现有的正则表达式引擎开始。)
另一方面,问题的真正根源(很可能)是您使用正则表达式的方式错误。要么你正试图做一些对单个正则表达式来说太复杂的事情,要么你的正则表达式是次优的
编辑:正则表达式耗时过长的典型原因是多个量词(?,+)导致病理性回溯。例如,如果您尝试匹配N“a”cha字符串
"(.*)<html>(.*)<head>(.*)</head>(.*)<body>(.*)</body>(.*)</html>(.*)"
<html><html><html><html><html><html><html><html><html><html>
<head><head><head><head><head><head><head><head><head><head>
</head></head></head></head></head></head></head></head></head></head>
<body><body><body><body><body><body><body><body><body><body><body>
</body></body></body></body></body></body></body></body></body></body>
@Timeable(limit = 1, unit = TimeUnit.SECONDS)
String yourMethod() {
// execution as usual
}
if (Thread.currentThread.isInterrupted()) {
throw new IllegalStateException("time out");
}
package org.test.xpath;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class InterruptableMatcherTest {
public static void main(String[] args) throws Exception{
Pattern pattern=Pattern.compile("^(([a-z])+.)+[A-Z]([a-z])+$");
String input="aaaaaaaaaaaaaaaaaaaaadddddddddddddddddddddddddddddddddddddddaaaaaaaaaaaa!";
PatternMatcher patternMatcher=new PatternMatcher(pattern, input);
Thread thread=new Thread(patternMatcher);
thread.start();
Thread.sleep(1*1000);
System.out.println("Done sleeping ...");
if(patternMatcher.running)patternMatcher.reset();//Without this call the program will hang
thread.join();
}//main closing
}//class closing
class PatternMatcher implements Runnable{
Pattern pattern;
Matcher matcher;
boolean running=false;
PatternMatcher(Pattern pattern, String input) {
this.pattern=pattern;
matcher=this.pattern.matcher(input);
}//constructor closing
@Override
public void run() {
running=true;
matcher.matches();
running=false;
}//run closing
void reset(){
System.out.println("Reset called ...");
matcher.reset("");
}//reset closing
}//class closing