如果超过最大允许时间,如何取消Libreoffice UNO API库将ms Office文件转换为PDF的过程 - java

我正在使用Libreoffice 6.0中的UNO API库(办公室)将ms office格式转换为PDF,办公室过程在服务器模式下满足多个同时请求。
通常,转换速度很快,但是在转换一些大文件时,例如xlsx或pptx,Soffice进程使用100%CPU,转换最多需要几分钟。
这是不可接受的,因为在此期间未处理并发请求。

为了处理这种情况,我尝试使用java.util.concurrent通过超时接口通过超时控制将一些子任务作为线程执行。但是,只有在转换的原始ms Office文件加载阶段发生挂起的情况下,它才有效。
如果转换过程已经开始,即使发生超时异常,Soffice进程也不会立即退出100%加载,而是将文档转换为pdf。
程序执行会暂停,以尝试处置加载的文档。

通过以下命令在Linux下启动SOffice进程:

Runtime.getRuntime().exec("/usr/lib64/libreoffice/program/soffice, --nologo, --nodefault, --norestore, --nocrashreport, --nolockcheck, --accept=socket,host=localhost,port=8100;urp;");

将MS Office文件转换为pdf的代码为简化形式:

public  void  convertFile(){
xRemoteContext = BootstrapSocketConnector.bootstrap(oooPath);
xRemoteServiceManager = xRemoteContext.getServiceManager();
Object desktop = null;
desktop = xRemoteServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xRemoteContext);
xComponentLoader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, desktop);
File mfile = new File(workingDir + myTemplate);
String sUrl = pathToURL(workingDir + myTemplate);
PropertyValue[] propertiesIn;
propertiesIn = new PropertyValue[2];
propertiesIn[0] = property("ReadOnly", Boolean.TRUE);
propertiesIn[1] = property("Hidden", Boolean.TRUE);
XComponent xComp = null;
try {
//xComp = xComponentLoader.loadComponentFromURL(sUrl, "_blank", 0, propertiesIn);
//The same via timeout control
xComp = callLibreLoad(sUrl, propertiesIn);
}
catch (TimeoutException ex) {
if(xComp!= null)
xComp.dispose();
...
}
// save as a PDF
XStorable xStorable = (XStorable) UnoRuntime.queryInterface(XStorable.class, xComp);
PropertyValue[] propertiesOut = new PropertyValue[2];
propertiesOut[0] = property("FilterName", formatfilter);
propertiesOut[1] = property("Overwrite", Boolean.TRUE);
String myResult = workingDir + fileNameOut;
try {
//xStorable.storeToURL(pathToURL(myResult), propertiesOut);
//The same via timeout control
callLibreStore(xStorable,pathToURL(myResult), propertiesOut);
}
catch (TimeoutException ex) {
if(xComp!= null)
 xComp.dispose();
...
}
if(xComp!= null)
 xComp.dispose();
}

函数callLibreLoad和callLibreStore使用Future接口进行超时控制:

private XComponent callLibreLoad(String sUrl, PropertyValue[] propertiesIn) throws Exception {
XComponent result = null;
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
 public Object call() throws IllegalArgumentException, com.sun.star.io.IOException {
 return xComponentLoader.loadComponentFromURL(sUrl, "_blank", 0, propertiesIn);
 }
};
Future<Object> future = executor.submit(task);
try {
 result = (XComponent) future.get(maxTimeout, TimeUnit.SECONDS); 
} 
finally 
{ future.cancel(true);} 
return result;
}

private void callLibreStore(XStorable xStorable, String sUrl, PropertyValue[] propertiesOut) throws Exception {
Integer result = null;
ExecutorService executor = Executors.newCachedThreadPool();
Runnable task = new Runnable() {
public void run() {
try {
xStorable.storeToURL(sUrl, propertiesOut);
} catch (com.sun.star.io.IOException e) {
log.error(e);
}
}
};
Future future = executor.submit(task);
try {
future.get(maxTimeout, TimeUnit.SECONDS); 
}
finally {
future.cancel(true); // may or may not desire this
}   
}

因此,当在函数callLibreLoad中发生超时异常时,SOffice进程将立即恢复到工作状态。
但是,如果稍后发生超时,则在函数callLibreStore中,即使发生超时并且转换线程被中断后,SOffice进程也会在尝试处理已加载的文档时保持100%加载状态一分钟以上,并执行代码xComp.dispose()。
在此期间,具有SOffice进程的Java线程的堆栈跟踪包含以下内容:

State: WAITING on com.sun.star.lib.uno.environments.remote.JobQueue@30af74b8
Total blocked: 455  Total waited: 1 967
Stack trace: 
java.lang.Object.wait(Native Method)
com.sun.star.lib.uno.environments.remote.JobQueue.removeJob(JobQueue.java:207)
com.sun.star.lib.uno.environments.remote.JobQueue.enter(JobQueue.java:316)
com.sun.star.lib.uno.environments.remote.JobQueue.enter(JobQueue.java:289)
com.sun.star.lib.uno.environments.remote.JavaThreadPool.enter(JavaThreadPool.java:81)
com.sun.star.lib.uno.bridges.java_remote.java_remote_bridge.sendRequest(java_remote_bridge.java:618)
com.sun.star.lib.uno.bridges.java_remote.ProxyFactory$Handler.request(ProxyFactory.java:145)
com.sun.star.lib.uno.bridges.java_remote.ProxyFactory$Handler.invoke(ProxyFactory.java:129)
com.sun.proxy.$Proxy211.close(Unknown Source)
com.componentplus.prom.libreoffice.LibreOfficeStationary.closeDocument(LibreOfficeStationary.java:425)
com.componentplus.prom.libreoffice.LibreOfficeStationary.convertFile(LibreOfficeStationary.java:393)
...

如果花费超过最大允许时间的话,如何迫使Soffice取消转换为pdf。

参考方案

一种可能是保存Process返回的Runtime.getRuntime().exec实例,例如在变量myProc中,然后在需要时调用myProc.destroy()终止进程。

java:继承 - java

有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

Java-如何将此字符串转换为日期? - java

我从服务器收到此消息,我不明白T和Z的含义,2012-08-24T09:59:59Z将此字符串转换为Date对象的正确SimpleDateFormat模式是什么? java大神给出的解决方案 这是ISO 8601标准。您可以使用SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM…

JAVA 8具有任何匹配属性的对象的过滤器列表 - java

我的要求是通过匹配任何属性的字符串来过滤对象列表。例如,假设Contact类具有三个属性:街道,城市,电话。我知道java流过滤器是如何工作的,在这里我必须将输入字符串与每个属性进行比较,如下所示:contactList.stream().filter(contact -> contact.getStreet().equals("dubai&…

Java-固定大小的列表与指定初始容量的列表之间的差异 - java

我在理解这一点上遇到了问题。当我们做 List<Integer> list = Arrays.asList(array); 我们不能在该列表上使用添加,删除之类的方法。我知道Arrays.asList()返回固定大小的列表。我不明白的是,如果我们创建一个具有指定初始容量的列表,例如List<Integer> list2 = new A…

从方法返回数组-Java - java

private static Coordinate[] getCircleCoordintaes() { Coordinate coordinates[] = {new Coordinate(0, 0)}; return coordinates; } 以上程序工作正常。在上面的程序中,返回的坐标数组首先初始化了数组使用这条线Coordinate coordi…