⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lib0113.html

📁 j2ee架构师手册
💻 HTML
字号:
<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Threading Strategies</title>
<link rel="STYLESHEET" type="text/css" href="images/xpolecat.css">
<link rel="STYLESHEET" type="text/css" href="images/ie.content.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/teamlib.gif" width="62" height="15" border="0" align="absmiddle"  alt="Team LiB"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href="LiB0112.html"><img src="images/previous.gif" width="62" height="15" border="0" align="absmiddle" alt="Previous Section"></a>
<a href="LiB0114.html"><img src="images/next.gif" width="41" height="15" border="0" align="absmiddle" alt="Next Section"></a>
</div></td></tr></table>
<br>
<div class="chapter">
<a name="ch17"></a>
<div class="section">
<h2 class="first-section-title"><a name="560"></a><a name="ch17lev1sec3"></a>Threading Strategies</h2><p class="first-para">Most applications have tasks that run asynchronously. These tasks can include scheduled "batch" work and long-running tasks users won't wait for. J2EE applications are no exception. Unfortunately, the J2EE specification makes no provision for work done asynchronously.</p>
<p class="para">Furthermore, the J2EE specification explicitly prohibits spawning threads directly or indirectly from within enterprise beans, so if you're going to <a name="561"></a><a name="IDX-235"></a>adhere to the specification, your hands are tied. This is one of the few negative features of the J2EE specification. It should offer a way to spawn asynchronous tasks with the understanding that the container could not provide transactional integrity for spawned tasks (e.g., you couldn't roll them back).</p>
<p class="para">Many developers provide a message-driven bean deployment for their asynchronous work so they can effectively spawn the task via JMS. Rather than an intentional misuse of JMS, this practice is a way to spawn asynchronous work while complying with the J2EE specification. It has the effect of twisting the container's arm into handling the threading issue.</p>
<p class="para">You have several choices for spawning asynchronous work in J2EE:</p>
<ul class="itemizedlist">
<li class="first-listitem">
<p class="first-para">Delegate the work out to a message-driven bean.</p>
</li>
<li class="listitem">
<p class="first-para">Delegate the work out to an RMI service that spawns needed threads.</p>
</li>
<li class="listitem">
<p class="first-para">Break the specification and spawn threads in stateless session beans.</p>
</li>
<li class="listitem">
<p class="first-para">Use the Timer service that's part of the EJB 2.1 specification (if you are running a 2.1-compliant container).</p>
</li>
</ul>
<p class="para">I favor delegating the work out to an RMI service. RMI services have no threading restriction, and their calls offer a tighter coupling than JMS message transmission. And because most container vendors offer clusterable RMI services, you're not sacrificing availability or scalability by using an RMI service to do asynchronous work.</p>
<p class="para">Although it's more programmatically convenient to break the specification, it's also risky. With many containers, you can get away with it in a stateless session bean context, but your code may not work in some containers and may break on a container upgrade.</p>
<p class="para">Only intermediate to advanced developers should attempt to write thread-safe code. Bugs from threaded code can be the most difficult bugs to find and fix.</p>
<p class="para">The following are just a few recommendations for creating thread-safe code. It is by no means a comprehensive review of threading. Entire books have been written on multithreaded and concurrent programming. My favorite is <a href="LiB0115.html#575" target="_parent" class="chapterjump">Lea (2000)</a>.</p>
<p class="para">
<b class="bold">Limit thread count to a manageable level.</b> Each thread consumes memory and causes more context switching within the JVM. Because of the resources and management overhead required, adding threads has diminishing returns. The point at which returns for additional threads diminish varies <a name="562"></a><a name="IDX-236"></a>among hardware configurations. Essentially, more threads are not necessarily better and do not necessarily increase throughput. In fact, depending on your hardware, more threads could decrease throughput.</p>
<p class="para">
<b class="bold">Avoid explicitly setting thread priority.</b> Only an advanced developer should consider explicitly setting the priority of threads because it greatly increases the complexity of debugging for a multithreaded application because it increases the chance of thread starvation. Thread starvation most often happens when a thread doesn't get execution time because the JVM is occupied with higher-priority tasks. The symptom of thread starvation is that work you spawned doesn't appear to ever run. Unless you have a specific reason for wanting a thread to have a lower priority, you should avoid the additional complexity.</p>
<p class="para">Setting thread priority would be especially dangerous if you're breaking the J2EE specification and initiating multithreaded code from within enterprise beans. You could inadvertently interfere with the normal operation of a container.</p>
<p class="para">
<b class="bold">Identify all threads as daemon threads.</b> The JVM makes a distinction between daemon and user threads. The JVM shuts down when all user threads terminate. If you spawn a user thread, it's best to make a provision for how it terminates. If you declare your threads as daemon threads, they do not interfere with a JVM shutdown. By the way, user threads are the default. Keep in mind that anything running daemon threads can be abruptly terminated at any point. <a class="internaljump" href="#ch17list07">Listing 17.7</a> is one way to declare daemon threads.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 17.7: </span>Declaring Threads as Daemons</span><a name="563"></a><a name="ch17list07"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
   1:// app code here
   2:
   3:Thread thread = new Thread(runnableClass);
   4:thread.setDaemon(true);
   5:thread.start();
   6:
   7:// app code here
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>
</div>
<p class="para">
<b class="bold">Log enough information on error so that you can reproduce an error situation in a single-threaded test case.</b> Debugging multithreaded code is often more difficult. Although most IDEs do support multithreading, the behavior of threads under an IDE often differs from their behavior at normal runtime. Error processing in spawned tasks needs to be robust enough to allow debugging a section of code within a single-threaded test case.</p>
<a name="564"></a><a name="IDX-237"></a>
<p class="para">
<b class="bold">Explicitly name all created threads.</b> Many containers have management extensions that will let you view the activity of each thread. As containers usually have dozens, if not hundreds, of threads, a specific thread is easier to find if it is descriptively named. <a class="internaljump" href="#ch17list08">Listing 17.8</a> illustrates how to name a thread.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 17.8: </span>Naming a Thread</span><a name="565"></a><a name="ch17list08"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
   1:// app code here
   2:
   3:Thread thread = new Thread(runnableClass);
   4:thread.setName("My thread name");
   5:thread.start();
   6:
   7:// app code here
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>
</div>
<p class="para">
<b class="bold">Perform a code review for all multithreaded code.</b> I generally promote code reviews for the entire business logic and data access layers. Since multi-threaded code can be especially difficult to debug, you should consider a code review even if you don't subject any of the other layers to the same level of scrutiny.</p>
<p class="para">Until recently, programmers were left to their own devices to code, execute, and manage multithreaded code. On a recent project, I had an extensive need for multithreaded code, but the skill level of the developers wasn't high enough to get everything coded safely within the project timeline. To make the deadline, I created a package to manage execution of our threaded code. I then recrafted and re-architected this package into the open source product called ThreadWorks (available at <a target="_top" class="url" href="http://sourceforge.net/projects/threadworks/">http://sourceforge.net/projects/threadworks/</a>).</p>
<div class="section">
<h3 class="sect3-title">
<a name="566"></a><a name="ch17lev2sec3"></a>Sample Threading Guidelines</h3>
<ul class="itemizedlist">
<li class="first-listitem">
<p class="first-para">Code all asynchronous tasks to implement <span class="fixed">java.lang.Runnable</span>.</p>
</li>
<li class="listitem">
<p class="first-para">Run all asynchronous tasks using ThreadWorks.</p>
</li>
<li class="listitem">
<p class="first-para">Perform a code review of all asynchronous tasks.</p>
</li>
<li class="listitem">
<p class="first-para">Centrally define all <span class="fixed">TaskManagers</span>. Consult the technical architect for a <span class="fixed">TaskManager</span> assignment for all asynchronous tasks.</p>
</li>
</ul>
</div>
</div>
</div><br>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/teamlib.gif" width="62" height="15" border="0" align="absmiddle"  alt="Team LiB"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href="LiB0112.html"><img src="images/previous.gif" width="62" height="15" border="0" align="absmiddle" alt="Previous Section"></a>
<a href="LiB0114.html"><img src="images/next.gif" width="41" height="15" border="0" align="absmiddle" alt="Next Section"></a>
</div></td></tr></table>
</body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -