blob: a3b7fa79aabbc1bb199e5fbbb2ce9f02345ab95c [file] [log] [blame]
<div class="wiki-content maincontent"><p>If you study thread allocation in ActiveMQ clients, you'll notice that by default there is one thread allocated by every session. This basically means that session will use its <a shape="rect" class="external-link" href="http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html" rel="nofollow">ThreadPoolExecutor</a> to execute its tasks. Up until version 5.7 this executor was unbound which could lead to OOM problems in rare case where are a large number of busy sessions in the same JVM could cause uncontrollable spikes in thread creation. </p>
<p>In 5.7 we bounded this executor to a maximum of 1000 threads by default, which we believe should be enough for most use cases. In case of large number of busy sessions, each of them could end up using large number of threads and eventually OOM your application. There are couple of things you can do. The first obvious thing is to decrease the max thread limit a session can use, like this:</p>
<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<script class="brush: java; gutter: false; theme: Default" type="syntaxhighlighter"><![CDATA[ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(&quot;tcp://localhost:61616&quot;);
connectionFactory.setMaxThreadPoolSize(10);
Connection conn = connectionFactory.createConnection();
conn.start();]]></script>
</div></div>
<p>On the other hand this can lead to the scenario where a single session exaust its max thread number. A default behavior of <code>ThreadPoolExecutor</code> in this case is to throw an exception, so you'll notice it. A workaround for this scenario is to provide a rejected task handler that will synchronize the execution with the calling thread, like this</p>
<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<script class="brush: java; gutter: false; theme: Default" type="syntaxhighlighter"><![CDATA[ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(&quot;tcp://localhost:61616&quot;);
connectionFactory.setRejectedTaskHandler(new ThreadPoolExecutor.CallerRunsPolicy());
Connection conn = connectionFactory.createConnection();
conn.start();]]></script>
</div></div>
<p>This will prevent the <code>ThreadPoolExecutor</code> from throwing an exception when it reaches its bound. Instead it will execute the rejected task in the calling thread.</p>
<p>Finally, you can eliminate these threads completly, you can do that by setting <code>alwaysSessionAsync</code> property to false</p>
<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<script class="brush: java; gutter: false; theme: Default" type="syntaxhighlighter"><![CDATA[ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(&quot;tcp://localhost:61616&quot;);
connectionFactory.setAlwaysSessionAsync(false);
Connection conn = connectionFactory.createConnection();
conn.start();]]></script>
</div></div>
<p>However you need to have in mind that this approach can affect performance of the whole system.</p>
<p>So there you go. In the unlikely scenario where your application has trouble with the number of threads created by JMS session, you can use one of the shown techniques to deal with it. As always there's no silver bullet for all scenarios, so measure and tune for your system.</p></div>