尝试使用jasper生成excel报告时,我在WebSphere中遇到以下异常。
ThreadMonitor W WSVR0605W: Thread "WebContainer : 0" (00000029) has been active for 647279 milliseconds and may be hung. There is/are 1 thread(s) in total in the server that may be hung.
尝试将默认线程池大小从20增加到50 并且还将WebContainer池大小从50增加到150.没有工作。
任何解决方案。
答案 0 :(得分:7)
您的错误消息告诉名为“WebContainer:0”的线程已经执行了647秒或10.7分钟的事情,并且JVM中的一个线程处于活动状态,我也挂起(活动时间超过阈值时间)。
挂起线程是Java EE应用程序中的一个线程,它被调用阻塞或正在监视器上等待释放锁定对象,以便线程可以使用它。挂起的线程可能来自简单的软件缺陷(例如无限循环)或更复杂的原因(例如,资源死锁)。如果线程数增加,该服务器的Java进程的CPU利用率可能会变高并且无响应。
有多种方法可以增加挂起时间(默认为10分钟),但不推荐。您已优化或限制Excel生成报告生成过程。我认为,报告你正在提取的是非常大的或者更多地用于生成数据库,基本上可能是由于代码错误。增加线程池的数量与您的问题无关。
在sysout.log中:在发布的警告消息的下面一行,应该对导致此问题的Java EE类有所了解。 FFDC也有助于解决这个问题。
默认情况下,挂起检测选项处于启用状态。您可以对其进行配置以适应环境,以便报告潜在的挂起。当检测到挂起的线程时,WAS会通知您,以便您可以解决问题。
使用挂起检测策略,您可以指定一个时间太长,无法完成工作单元。线程监视器检查所有托管线程,包括Web容器线程。
名称: com.ibm.websphere.threadmonitor.interval
值:将询问所选应用程序服务器中托管线程的频率(以秒为单位)。
默认值: 180秒(3分钟)。
名称: com.ibm.websphere.threadmonitor.dump.java
值:设置为true以在检测到挂起线程并且打印WSVR0605W消息时执行dumpThreads函数。可以分析javacore转储的线程部分以确定报告的线程
默认值: false(0)。
名称: com.ibm.websphere.threadmonitor.threshold
值:线程在被视为挂起之前可以处于活动状态的时间长度(以秒为单位)。任何被检测为活动时间超过此时间长度的线程都会被报告为挂起 默认值:默认值为600秒(十分钟)。
名称: com.ibm.websphere.threadmonitor.false.alarm.threshold
值:可能发生错误警报的次数(T) 在自动增加阈值之前。有可能是一个 报告为挂起的线程最终完成其工作, 导致误报。大量这些事件表明 阈值太小了。挂起检测设备可以 自动响应这种情况:对于每个T误报警, 阈值T增加1.5倍。将值设置为 零(或更少)以禁用自动调整。 (链接到 检测J2EE应用程序中的挂起线程以获取有关误报的信息 默认: 100
要禁用挂起检测选项,请将com.ibm.websphere.threadmonitor.interval属性设置为小于或等于零。
答案 1 :(得分:5)
这不是例外。如您所见,它具有W
级别,即警告(ThreadMonitor W WSVR0605W
)。它只是告诉您,您的报告生成时间非常长。超过647279毫秒。当您进一步查看日志时,您很可能会注意到类似的消息,告知您的线程已完成作业,并且不再被挂起。
增加WebContainer池与此无关。您必须查看创建报告的课程,如果能够更快地完成,请查看。
另一种解决方案是使用Async Beans或JMS(不幸的是在v7上,因此没有EJB 3.1或异步servlet可用)将报告创建为异步任务,将其存储到数据库或文件系统中,然后检索报告完成后使用单独的请求。
答案 2 :(得分:0)
在我们的团队中,我们发现Websphere 8.5.5.13从未关闭挂起的线程,因此我们的团队提供了一种用于处理大量并发线程的事务系统的解决方案,因此我们找到了使用Java的解决方案,而不是永远挂起参数设置后8超时。 下面的代码演示了如何编写一个在超时后执行关键任意代码的函数的演示。
public class MyFactory
{
TimeUnit timeUnit=TimeUnit.MILLISECONDS;
int REQUEST_TIMEOUT=50;
int MAX_THREADS=1;
ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
public Function<Supplier<?>, ?> executeWithTimeout = typeSupplier-> {
final ExecutorService singleCallableExec =
Executors.newSingleThreadExecutor();
try
{
return executor.submit(()-> {
try { return singleCallableExec.submit(()->{
return typeSupplier.get();
}).get(REQUEST_TIMEOUT, timeUnit);
}
catch (Exception t2) { singleCallableExec.shutdownNow(); throw t2; }
finally {
Optional.of(singleCallableExec)
.filter(e -> !e.isShutdown())
.ifPresent(ExecutorService::shutdown);
}
}).get();
}
catch (InterruptedException | ExecutionException e)
{
throw new RuntimeException(e);
}
};
因此可以将其放入工厂类中,并在需要执行可能永远超时的关键代码的每个线程中调用此方法,这对于发送超时异常(引发警报而不是等待系统退出)很有用资源
public static void main (String args[])
{
MyFactory mf=new MyFactory();
try
{
long result = (long) mf.executeWithTimeout.apply(()->mf.longCalculation());
System.out.println("Result:" + result);
}
catch (Exception te)
{
if (te instanceof RuntimeException &&
te.getCause() != null && te.getCause() instanceof ExecutionException
&& te.getCause().getCause() != null && te.getCause().getCause()
instanceof TimeoutException)
{
System.out.println(new Date() + " Raising alarm, TimeoutException");
}
}
finally
{
mf.executor.shutdownNow();
}
}
public long longCalculation()
{
long result=LongStream.range(0, (long) Math.pow(2,32)).max().getAsLong();
System.out.println(new Date() + " Calculation result " + result);
return result;
}
}