用我的语法,当我分析像这样的条目时:
ZZ9->ZZ9_LINHA := &(_cAlias+"->(CONTAEBTA)" )+& (_cAlias+"->(REGISTRO)" )+& (_cAlias+"->(TRANSACAO)" )+& (_cAlias+"->(REFERENCIA)" )+;
&(_cAlias+"->(REFPAGTO)" )+& (_cAlias+"->(STATTRANSA)" )+& (_cAlias+"->(NAOUSADO1)" )+& (_cAlias+"->(NAOUSADO2)" )+;
&(_cAlias+"->(NUMFATURA)" )+& (_cAlias+"->(INDDISPUTA)" )+& (_cAlias+"->(DATFATURAM)" )+& (_cAlias+"->(DATPARTIDA)" )+;
&(_cAlias+"->(NOMVIAJANT)" )+& (_cAlias+"->(INIVIAJANT)" )+& (_cAlias+"->(ROTA)" )+& (_cAlias+"->(NAOUSADO3)" )+;
&(_cAlias+"->(CENTROCUST)" )+& (_cAlias+"->(STATUSPGTO)" )+& (_cAlias+"->(VALORPAGTO)" )+& (_cAlias+"->(SINALPAGTO)" )+;
&(_cAlias+"->(VALORTRANS)" )+& (_cAlias+"->(SINALTRANS)" )+& (_cAlias+"->(NAOUSADO4)" )+& (_cAlias+"->(NAOUSADO5)" )+;
&(_cAlias+"->(NAOUSADO6)" )+& (_cAlias+"->(NAOUSADO7)" )+& (_cAlias+"->(NUMBILHETE)" )+& (_cAlias+"->(CIAAEREA)" )+;
&(_cAlias+"->(DATEMISSAO)" )+& (_cAlias+"->(TAXAEMBARQ)" )+& (_cAlias+"->(SINALTXEMB)" )+& (_cAlias+"->(VLRBILHET)" )+;
&(_cAlias+"->(SINBILHET)" )+& (_cAlias+"->(NAOUSADO8)" )+& (_cAlias+"->(NAOUSADO9)" )+& (_cAlias+"->(TIPDESPESA)" )+;
&(_cAlias+"->(DATDESPESA)" )+& (_cAlias+"->(DEPTO)" )+& (_cAlias+"->(MATRICULA)" )+& (_cAlias+"->(CODIATA)" )+;
&(_cAlias+"->(NAOUSADOA)" )+& (_cAlias+"->(REQVIAGEM)" )+& (_cAlias+"->(NAOUSADOB)" )+& (_cAlias+"->(CLASSEVOO)" )
解析器变得越来越慢,并且使用越来越多的内存。
如果工作线程已暂停,则ANTLR4堆栈为:
我现在无法对此语法进行重构。因此,我正在寻找一种通过超时停止执行解析器的方法。
我已经使用ExecutorService和Future尝试了以下方法:
public class MyParserIsolateThread implements Callable<ParseTree> {
public String ppo;
public MyParserIsolateThread(String ppoInfo)
{
this.ppo = ppoInfo;
}
@Override
public ParseTree call() throws Exception {
NoCaseANTLRStringStream input = new NoCaseANTLRStringStream(this.ppo);
MyLexer lexer = new MyLexer(input);
CommonTokenStream token = new CommonTokenStream(lexer);
MyParser parser = new MyParser(token);
AntlrToSonarErrorListener error = new AntlrToSonarErrorListener(null,null,ppo);
parser.addErrorListener(error);
long startTime = System.currentTimeMillis();
System.out.println("Starting parsing...");
ParseTree tree = parser.program();
long estimatedTime = System.currentTimeMillis() - startTime;
System.out.println("Parse Finished. Elapsed time:" + estimatedTime);
return tree;
}
}
MyParserIsolateThread threadParser = new MyParserIsolateThread(ppo);
ExecutorService executorService = Executors.newFixedThreadPool(1);
Future<ParseTree> result = executorService.submit(threadParser);
try {
ParseTree tree = result.get(60, TimeUnit.SECONDS);
System.out.println("Parser OK ");
} catch (Exception e) {
// interrupts if there is any possible error
System.out.println("too long parsing...");
result.cancel(true);
}
executorService.shutdownNow();
try {
executorService.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("end.");
如果我使用一个耗时超过60秒的条目,则会正确显示该消息,但是即使使用shutdownNow,工作线程和池线程也会继续运行。
所以,
有什么方法可以停止。吗?
我想到了不时调用的回调函数,以查看是否应该停止。
我不想使用Thread,而使用.stop(),因为它已被弃用且不安全。
任何想法?
最佳答案
您可以使用与BailOutErrorStrategy
相同的方法:万一发生错误,它会引发异常,解析机制无法捕获该异常。
在运行解析器之前,将它添加到解析器中。覆盖enterEveryRule
方法,并在调用该方法时检查解析器到目前为止运行的时间。如果超时,则抛出您的停止异常,该异常将立即停止解析运行。您可以在代码中捕获此异常,以查看是否已达到超时。