由于在java中显式创建线程而导致的问题

时间:2014-07-07 13:50:04

标签: java multithreading websphere out-of-memory ibm-mq

我正在处理OutOfMemory中的WAS 6.1以下异常。

Exception in thread "UnitHoldingsPolicySummary" java.lang.OutOfMemoryError: unable to create new native thread.

我已就此做了大量研究以防止这种情况发生。在谷歌搜索之后,我发现,当Native内存由于同时创建大量线程而耗尽时会发生这种情况。

现在,在分析了下面的日志之后,我们可以弄清楚,在应用程序内部,线程是明确创建的,我读到这是一个非常非常糟糕的做法。 (专家可以确认一下吗?)

07/07/14 08:50:38:165 BST] 0000142c SystemErr     R Exception in thread "xxxxxx" java.lang.OutOfMemoryError: unable to create new native thread
        at java.lang.Thread.start0(Native Method)
        at java.lang.Thread.start(Thread.java:574)
        at com.fp.sv.controller.business.thread.xxxxxxxxxexecute(Unknown Source)
        at com.fp.sv.controller.business.thread.xxxxxxxxx.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:595) 

我更喜欢WAS管理,并且不具备Java中的Java和线程创建方面的知识。现在我需要与开发人员讨论这个问题,但在此之前我想100%确认我的发现是正确的,开发人员应该通过不明确地创建线程来纠正代码。

在将此问题归咎于代码之前,我需要在应用程序服务器端检查所有内容吗?

在solaris上,我正在触发命令pmap -x 9547|grep -i stack|wc -l以检查在该实例时间上创建了多少个线程。我可以在“OutOfMemory”期间看到'问题,这个数字非常高。

请问您确认此命令是否是检查当前活动线程数的好方法?

使用我的最新发现编辑问题

此外,当出现此问题时,由于WAS没有从队列中获取消息,因此在同一个MQ队列中堆积起来。我可以在特定于应用程序的日志中看到以下错误。

Non recoverable Exception detected whilst connecting to queue manager or response queue Underlying reason = MQJE001: Completion Code 2, Reason 2102

这个问题也可以与MQ相关吗?这又导致OutOfMemory问题?

此致 拉胡

2 个答案:

答案 0 :(得分:1)

为虚拟机实现线程系统有不同的可能性。两种极端形式是:

  1. 绿色线程:所有Java Thread实例都在一个本机操作系统线程中进行管理。如果方法在native调用内阻塞,则会导致此实现变得复杂,这可能会导致问题。最后,实现者需要引入 renegade threads 来保存本机锁以克服这些限制。
  2. 本机线程:每个Java Thread实例都由本机操作系统线程支持。
  3. 对于绿色线程的命名限制,所有现代JVM实现(包括HotSpot)都选择后面的实现。这意味着操作系统需要为每个创建的线程保留一些内存。此外,创建此类线程需要一些运行时开销,因为它需要与底层操作系统直接交互。在某些时候,这些成本会累积,操作系统会拒绝创建新线程,以防止整个系统的稳定性。

    因此应该将线程合并为resue。对象池通常被认为是不好的做法,因为许多程序员使用它来简化JVM的垃圾收集器。这不再有用,因为现代垃圾收集器已经过优化,可以处理短生物。今天,通过汇集对象,您可能会相反减慢系统速度。但是,如果对象由昂贵的本机资源(作为Thread)支持,则仍建议使用池。查看ExecutorService以了解在Java中汇集线程的规范方法。

    通常,请考虑线程的上下文切换是昂贵的。您不应该为小任务创建新线程,这会降低您的应用程序速度。而是使您的应用程序更少并发。您只有一些核心可以在一开始就同时工作,创建比您的(非虚拟)核心更多的线程不会提高运行时性能。你是否实施了某种分而治之的算法?查看Java的ForkJoinPool

答案 1 :(得分:0)

是的,这是一种不好的做法。通常,您不管理Java EE服务器内的线程。通常"通常"我的意思是"在开发业务应用程序时#34;。

根据http://www.oracle.com/technetwork/java/restrictions-142267.html

  

为什么不允许线程创建和管理?

     

EJB规范为EJB容器分配责任   用于管理线程。允许企业bean实例创建和   管理线程会干扰容器的控制能力   其组件'生命周期。线程管理不是一项业务   函数,它是一个实现细节,通常很复杂   和平台特定的。让容器管理线程减轻   处理线程问题的企业bean开发人员。   多线程应用程序仍然可行,但控制   多线程位于容器中,而不是在企业中   豆。

但是,我不认为您的日志表明正在明确创建线程。如果您想100%确定,请反编译部署并查看这些行中的代码。

另请看一下:

"java.lang.OutOfMemoryError : unable to create new native Thread"

而且:

https://plumbr.eu/outofmemoryerror/unable-to-create-new-native-thread

关于您的应用使用的线程数,我尝试使用JConsole或VisualVm等监控工具。