📄 097-103.html
字号:
<HTML>
<HEAD>
<META name=vsisbn content="1558515682"><META name=vstitle content="Java Digital Signal Processing"><META name=vsauthor content="Douglas A. Lyon"><META name=vsimprint content="M&T Books"><META name=vspublisher content="IDG Books Worldwide, Inc."><META name=vspubdate content="11/01/97"><META name=vscategory content="Web and Software Development: Programming, Scripting, and Markup Languages: Java"><TITLE>Java Digital Signal Processing:Java Programming: The Basics</TITLE>
<!-- HEADER --><STYLE type="text/css"> <!-- A:hover { color : Red; } --></STYLE><META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<!--ISBN=1558515682//-->
<!--TITLE=Java Digital Signal Processing//-->
<!--AUTHOR=Douglas A. Lyon//-->
<!--PUBLISHER=IDG Books Worldwide, Inc.//-->
<!--IMPRINT=M & T Books//-->
<!--CHAPTER=2//-->
<!--PAGES=097-103//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//-->
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="093-097.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="103-107.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
</P>
<H3><A NAME="Heading17"></A><FONT COLOR="#000077">Threads</FONT></H3>
<P>Threads enable parallelism within a program. Threading provides a low-overhead context switch. In the DiffCAD program, we use threads to display a digital clock in the lower-left corner of the screen, shown in Figure 2.5.
</P>
<P><A NAME="Fig5"></A><A HREF="javascript:displayWindow('images/02-05.jpg',153,21 )"><IMG SRC="images/02-05t.jpg"></A>
<BR><A HREF="javascript:displayWindow('images/02-05.jpg',153,21)"><FONT COLOR="#000077"><B>Figure 2.5</B></FONT></A> The digital clock.</P>
<P>The Java specification says that threads use a shared memory paradigm to perform interthread communication. This usage is typical, but threads can use any number of techniques to perform communication. For example, you could simulate a distributed computation scheme using threads and another communication technique, perhaps involving the socket API. The Java language specification also says that “threads may be supported by having many hardware processors.” In fact, this capability is not yet implemented on any virtual machine that we know of, although we expect this situation to change. Java uses the <I>synchronized</I> statement to make sure that a method contained within a thread is executed atomically. <I>Atomic</I> operations appear to happen all at once. Thus, synchronized methods cannot be interrupted by other threads. To put it another way, <I>synchronized</I> methods prevent other threads from running. If the synchronized method takes longer than the time provided by a sleep method invocation, the <I>synchronized</I> method may not be updated frequently enough. The <I>Thread</I> class hierarchy is shown in Figure 2.6.</P>
<P><A NAME="Fig6"></A><A HREF="javascript:displayWindow('images/02-06.jpg',240,49 )"><IMG SRC="images/02-06t.jpg"></A>
<BR><A HREF="javascript:displayWindow('images/02-06.jpg',240,49)"><FONT COLOR="#000077"><B>Figure 2.6</B></FONT></A> The <I>Thread</I> class hierarchy
</P>
<P>Synchronized methods allow only one thread to access data at a time, this can prevent data corruption. Synchronized methods can also prevent <I>race</I> conditions, which arise when different threads have access to the same variable in an instance. If both threads access the instance variable at the same time, it is a “race” to see which thread will effect the change first, (hence the term). The solution is to create synchronized accessor methods for every variable in an instance. Then any change made through the synchronized accessor methods will be atomic. If there is a mix of synchronized accessor methods and asynchronous accessor methods, the alterations to the instance variables’ values are not atomic and the race condition may still exist. Threads are run with a round-robin, priority-queue-driven scheduler. This arrangement can be overridden with custom schedulers (whose composition is beyond the scope of this text). Furthermore, if the Java virtual machine is written that takes advantage of multiple CPUs, task completion on multiple threads will not be predictable.</P>
<P>To make a new thread, subclass the <I>Thread</I> class and implement the <I>run()</I> method. Instantiate the thread subclass and then invoke the <I>start()</I> method on the instance to begin thread execution.</P>
<P>Another way to make a thread is to use the <I>Runnable</I> interface. Any class that implements the <I>Runnable</I> interface must implement the <I>run</I> method, which is invoked when the thread is started. The thread is started when an instance of the <I>Runnable</I> class is passed to the <I>Thread</I> constructor and <I>start</I> is invoked.</P>
<P>The following is a simple thread example called <I>RaceThread</I>.</P>
<BLOCKQUOTE>
<P><FONT SIZE="-1"><HR>The <I>RaceThread</I> class extends the <I>Thread</I> class. To run an instance of <I>RaceThread</I>, you must make an instance of <I>RaceThread</I> and use this instance as the target of a <I>run()</I> invocation.<HR></FONT>
</BLOCKQUOTE>
<!-- CODE //-->
<PRE>
1. class RaceThread extends Thread {
2. public void run() {
3. while (true) {
4. System.out.println(“Priority=\t”
+ getPriority());
5. System.out.println(“toString=\t”+
toString());
6. System.out.println(“getName=\t”+
getName());
7. System.out.println(“isDaemon=\t”+
isDaemon());
8. System.out.println(“isAlive=\t”+
isAlive());
9. try {Thread.sleep(10000);}
10. catch (InterruptedException e) {}
11. }
12. }
13. }
</PRE>
<!-- END CODE //-->
<P>Take a close look at the <I>run</I> method. The <I>run</I> method is at the heart of any thread’s activity. Classes that extend the <I>Thread</I> class must implement the <I>run</I> method or they will not run (they compile, but upon launch nothing happens). Next, look at the <I>while</I> statement on line 3. It is an infinite loop! It will run until terminated. This makes line 9 and 10 crucial. Line 9 will put the thread to sleep for 10,000 milliseconds (10 seconds). The argument to <I>Thread.sleep</I> must be a long integer. This makes sense when you consider that there are</P>
<P>2<SUP>log<SUB>2</SUB>(1000*60*60*24)</SUP> = 2<SUP>26</SUP></P>
<P>milliseconds in a day. To put it another way, a signed 32-bit integer will overflow in</P>
<P>2<SUP>31</SUP> – 1</P>
<P>milliseconds, which is slightly more than 3.5 weeks. A 64-bit integer will overflow in 292.4 billion years. At that point we will probably not be using 64-bit integers (or even FORTRAN). To put this in perspective, the sun’s corona will have engulfed Earth by then, and this book will almost certainly be out of print. To run the <I>RaceThread</I> example, use the following code:</P>
<!-- CODE SNIP //-->
<PRE>
RaceThread r = new RaceThread();
r.start();
</PRE>
<!-- END CODE SNIP //-->
<P>The following will be printed every 10 seconds at the console:
</P>
<!-- CODE SNIP //-->
<PRE>
Priority = 5
toString = Thread[Thread-2,5,main]
getName = Thread-2
isDaemon = false
isAlive = true
</PRE>
<!-- END CODE SNIP //-->
<P>Java makes threading a part of the <I>java.lang</I> package. This means that you can expect threading to be implemented even on an embedded picoJava controller. Having threading described in the Java specification means that multithreaded Java programs are as portable as Java.</P>
<P>The following code creates the digital clock in DiffCAD:</P>
<!-- CODE SNIP //-->
<PRE>
1. import java.util.*;
2. import java.awt.*;
3. import java.applet.Applet;
</PRE>
<!-- END CODE SNIP //-->
<P>Lines 1, 2, and 3 import the packages that DiffCAD needs in the <I>DigitalThread</I> class.</P>
<!-- CODE SNIP //-->
<PRE>
4. // DigitalThread must extend applet to getFontMetrics.
5. public class DigitalThreads extends Applet implements
Runnable {
</PRE>
<!-- END CODE SNIP //-->
<P>A class that implements <I>Runnable</I> must provide an implementation for the <I>run</I> method. Note that the <I>Thread</I> class has a specific type:</P>
<!-- CODE SNIP //-->
<PRE>
6. Thread runner;
</PRE>
<!-- END CODE SNIP //-->
<P>The Java machine will execute threads until they die. A thread is dead when its <I>run()</I> method returns or the <I>stop()</I> method is invoked.</P>
<!-- CODE SNIP //-->
<PRE>
7. Graphics g;
8. Frame f;
9. public void start() {
10. if (runner == null) {
11. runner = new Thread(this);
12. runner.start();
13. }
14. }
</PRE>
<!-- END CODE SNIP //-->
<P>The <I>stop</I> method allows you to invoke the <I>stop</I> method of a thread that has already been stopped. You may need to stop a thread in order to avoid a race condition or to make sure that system resources are made available for other threads. After the <I>stop()</I> method is invoked, it may be that the thread should be restarted. Lines 9-14 enable you to start a thread that has been stopped. You can invoke <I>start</I> on a method that is already started.</P>
<!-- CODE SNIP //-->
<PRE>
15. public void stop() {
16. if (runner != null) {
17. runner.stop();
18. runner = null;
19. }
20. }
</PRE>
<!-- END CODE SNIP //-->
<P>In line 21, note the use of the <I>synchronized</I> keyword. This makes the <I>draw</I> method atomic. <I>Draw</I> is one method we do not want to interrupt, particularly with another <I>draw</I> method. Should this occur, <I>draw</I> could leave the screen in an inconsistent state. The frame field, <I>f</I>, is set by the calling program. On line 25 we see that the date is being accessed from the <I>java.util</I> API.</P>
<!-- CODE SNIP //-->
<PRE>
21. synchronized private void draw() {
22. Dimension dim = f.size();
23. int height = dim.height - 60;
24. int width = dim.width;
25. Date theDate = new Date();
26. String date_string = theDate.toString();
</PRE>
<!-- END CODE SNIP //-->
<P>A notable problem with the <I>theDate.toString()</I> method is that it will yield different returns on different platforms. For example, on Microsoft’s’ J++ compiler, running under Windows 95/NT we found that the Eastern Daylight Time or Standard Time (EDT, ST) initials are present. For this graphics routine to work, we must therefore query the graphics context for the font metrics, to size a background-fill rectangle properly.</P>
<!-- CODE SNIP //-->
<PRE>
27. int xloc = 10;
28. int yloc = dim.height - 60;
</PRE>
<!-- END CODE SNIP //-->
<P>The upper-left corner of the screen is the origin in Java. Thus, (dim.width, dim.height) are the coordinates of the lower-right corner.
</P>
<!-- CODE SNIP //-->
<PRE>
29. // g.setFont(f);
30. // get the string width in pixels.
31. int string_width = getFontMetrics(
32. g.getFont()).stringWidth(date_string);
33. int string_height = getFontMetrics(
34. g.getFont()).getHeight();
</PRE>
<!-- END CODE SNIP //-->
<P>Line 32 uses the graphics context, <I>g</I>, which is set using the calling program. Thus, both the graphics context and the frame for the clock must be given before this program will have a draw target. Line 35 draws a filled clear rectangle under the string so that the string can be seen clearly even if there is clutter on the screen.</P>
<!-- CODE SNIP //-->
<PRE>
35. g.clearRect(xloc,yloc,string_width, string_height);
36. g.drawString(date_string, xloc,height+xloc);
37. }
</PRE>
<!-- END CODE SNIP //-->
<P>On line 38 we see the <I>run</I> method. The <I>run</I> method is required of classes that implement the <I>runnable</I> interface. Note that the only synchronized method, <I>draw</I>, is invoked on line 40. This method gives us a return within a second, which is the sleep time for this thread, as seen on line 41.</P>
<!-- CODE SNIP //-->
<PRE>
38. public void run() {
39. while (true) {
40. draw();
41. try {Thread.sleep(1000);}
42. catch (InterruptedException e) {}
43. }
44. }
45. }
</PRE>
<!-- END CODE SNIP //-->
<P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="093-097.html">Previous</A></TD>
<TD><A HREF="../ewtoc.html">Table of Contents</A></TD>
<TD><A HREF="103-107.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<hr width="90%" size="1" noshade><div align="center"><font face="Verdana,sans-serif" size="1">Copyright © <a href="/reference/idgbooks00001.html">IDG Books Worldwide, Inc.</a></font></div>
<!-- all of the reference materials (books) have the footer and subfoot reveresed --><!-- reference_subfoot = footer --><!-- reference_footer = subfoot --></BODY></HTML><!-- END FOOTER -->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -