📄 chapter14.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source:
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:Tjava14.rtf
Application Directory:c:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:02/04/2000
Translation Time:23:25:55
Translation Platform:Win32
Number of Output files:27
This File:Chapter14.html
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>14: Multiple threads</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
<a href="http://www.MindView.net">
<img src="mindview-head.gif" alt="MindView Inc." BORDER = "0"></a>
<CENTER>
<FONT FACE="Verdana" size = "-1">
[ <a href="README-HTML.txt">Viewing Hints</a> ]
[ <a href="http://www.mindview.net/TIJ2/index.html">2nd Edition</a> ]
[ <a href="http://www.mindview.net/MailingList.html">Free Newsletter</a> ] <br>
[ <a href="http://www.mindview.net/Training.html">Seminars</a> ]
[ <a href="http://www.mindview.net/javaCD2.html">Seminars on CD ROM</a> ]
[ <a href="http://www.mindview.net/CPPServices/#ConsultingServices">Consulting</a> ]
</FONT>
<H2><FONT FACE="Verdana">
Thinking in Java, 1st edition</FONT></H2>
<H3><FONT FACE="Verdana">©1998 by Bruce Eckel</FONT></H3>
<FONT FACE="Verdana" size = "-1">
[ <a href="Chapter13.html">Previous Chapter</a> ]
[ <a href="SimpleContents.html">Short TOC</a> ]
[ <a href="Contents.html">Table of Contents</a> ]
[ <a href="DocIndex.html">Index</a> ]
[ <a href="Chapter15.html">Next Chapter</a> ]
</FONT>
</CENTER>
</P></DIV><A NAME="Chapter_16"></A><A NAME="_Toc375545471"></A><A NAME="_Toc407441458"></A><A NAME="_Toc408018744"></A><A NAME="Heading480"></A><FONT FACE = "Verdana"><H1 ALIGN="LEFT">
14: Multiple threads</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" SIZE=4>Objects provide a way to
divide a program up into independent sections. Often, you also need to turn a
program into separate, independently-running subtasks.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Each of these independent subtasks
is called a <A NAME="Index2437"></A><A NAME="Index2438"></A><I>thread</I>, and
you program as if each thread runs by itself and has the CPU to itself. Some
underlying mechanism is actually dividing up the CPU time for you, but in
general, you don’t have to think about it, which makes programming with
multiple threads a much easier task.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Some definitions are useful at this
point. A <A NAME="Index2439"></A><I>process</I> is a self-contained running
program with its own address space. A
<A NAME="Index2440"></A><I>multitasking</I> operating system is capable of
running more than one process (program) at a time, while making it look like
each one is chugging along by periodically providing CPU cycles to each process.
A thread is a single sequential flow of control within a process. A single
process can thus have multiple concurrently executing threads.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">There are many possible uses for
multithreading, but in general, you’ll have some part of your program tied
to a particular event or resource, and you don’t want to hang up the rest
of your program because of that. So you create a thread associated with that
event or resource and let it run independently of the main program. A good
example is a “quit” button – you don’t want to be forced
to poll the quit button in every piece of code you write in your program and yet
you want the quit button to be responsive, as if you <I>were</I> checking it
regularly. In fact, one of the most immediately compelling reasons for
multithreading is to produce a responsive user
interface.</FONT><A NAME="_Toc375545472"></A><A NAME="_Toc408018745"></A><BR></P></DIV>
<A NAME="Heading481"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Responsive user interfaces<BR><A NAME="Index2441"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">As a starting point, consider a
program that performs some CPU-intensive operation and thus ends up ignoring
user input and being unresponsive. This one, a combined applet/application, will
simply display the result of a running counter:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: Counter1.java</font>
<font color=#009900>// A non-responsive user interface</font>
<font color=#0000ff>package</font> c14;
<font color=#0000ff>import</font> java.awt.*;
<font color=#0000ff>import</font> java.awt.event.*;
<font color=#0000ff>import</font> java.applet.*;
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Counter1 <font color=#0000ff>extends</font> Applet {
<font color=#0000ff>private</font> <font color=#0000ff>int</font> count = 0;
<font color=#0000ff>private</font> Button
onOff = <font color=#0000ff>new</font> Button(<font color=#004488>"Toggle"</font>),
start = <font color=#0000ff>new</font> Button(<font color=#004488>"Start"</font>);
<font color=#0000ff>private</font> TextField t = <font color=#0000ff>new</font> TextField(10);
<font color=#0000ff>private</font> <font color=#0000ff>boolean</font> runFlag = <font color=#0000ff>true</font>;
<font color=#0000ff>public</font> <font color=#0000ff>void</font> init() {
add(t);
start.addActionListener(<font color=#0000ff>new</font> StartL());
add(start);
onOff.addActionListener(<font color=#0000ff>new</font> OnOffL());
add(onOff);
}
<font color=#0000ff>public</font> <font color=#0000ff>void</font> go() {
<font color=#0000ff>while</font> (<font color=#0000ff>true</font>) {
<font color=#0000ff>try</font> {
Thread.currentThread().sleep(100);
} <font color=#0000ff>catch</font> (InterruptedException e){}
<font color=#0000ff>if</font>(runFlag)
t.setText(Integer.toString(count++));
}
}
<font color=#0000ff>class</font> StartL <font color=#0000ff>implements</font> ActionListener {
<font color=#0000ff>public</font> <font color=#0000ff>void</font> actionPerformed(ActionEvent e) {
go();
}
}
<font color=#0000ff>class</font> OnOffL <font color=#0000ff>implements</font> ActionListener {
<font color=#0000ff>public</font> <font color=#0000ff>void</font> actionPerformed(ActionEvent e) {
runFlag = !runFlag;
}
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
Counter1 applet = <font color=#0000ff>new</font> Counter1();
Frame aFrame = <font color=#0000ff>new</font> Frame(<font color=#004488>"Counter1"</font>);
aFrame.addWindowListener(
<font color=#0000ff>new</font> WindowAdapter() {
<font color=#0000ff>public</font> <font color=#0000ff>void</font> windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(300,200);
applet.init();
applet.start();
aFrame.setVisible(<font color=#0000ff>true</font>);
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">At this point, the AWT and applet
code should be reasonably familiar from Chapter 13. The <B>go( )</B> method
is where the program stays busy: it puts the current value of <B>count</B> into
the <B>TextField t</B>, then increments <B>count</B>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Part of the infinite loop inside
<B>go( )</B> is to call <B>sleep( )</B>.
<A NAME="Index2442"></A><B>sleep( )</B> must be associated with a
<A NAME="Index2443"></A><B>Thread</B> object, and it turns out that every
application has <I>some</I> thread associated with it. (Indeed, Java is based on
threads and there are always some running along with your application.) So
regardless of whether you’re explicitly using threads, you can produce the
current thread used by your program with <B>Thread.
currentThread()<A NAME="Index2444"></A></B> (a static method of the <B>Thread
</B>class) and then call <B>sleep( )</B> for that thread.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Note that <B>sleep( )</B> can
throw <A NAME="Index2445"></A><B>InterruptedException</B>, although throwing
such an exception is considered a hostile way to break from a thread and should
be discouraged. (Once again, exceptions are for exceptional conditions, not
normal flow of control.) Interrupting a sleeping thread is included to support a
future language feature.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When the <B>start</B> button is
pressed, <B>go( )</B> is invoked. And upon examining <B>go( )</B>, you
might naively think (as I did) that it should allow multithreading because it
goes to sleep. That is, while the method is asleep, it seems like the CPU could
be busy monitoring other button presses. But it turns out that the real problem
is that <B>go( )</B> never returns, since it’s in an infinite loop,
and this means that <B>actionPerformed( )</B> never returns. Since
you’re stuck inside <B>actionPerformed( )</B> for the first keypress,
the program can’t handle any other events. (To get out, you must somehow
kill the process; the easiest way to do this is to press Control-C in the
console window.)</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The basic problem here is that
<B>go( )</B> needs to continue performing its operations, and at the same
time it needs to return so <B>actionPerformed( )</B> can complete and the
user interface can continue responding to the user. But in a conventional method
like <B>go( )</B> it cannot continue <I>and</I> at the same time return
control to the rest of the program. This sounds like an impossible thing to
accomplish, as if the CPU must be in two places at once, but this is precisely
the illusion that threading provides. The thread model (and programming support
in Java) is a programming convenience to simplify juggling several operations at
the same time within a single program. With threads, the CPU will pop around and
give each thread some of its time. Each thread has the consciousness of
constantly having the CPU to itself, but the CPU’s time is actually sliced
between all the threads.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><A NAME="Index2446"></A><A NAME="Index2447"></A><FONT FACE="Georgia">Threading
reduces computing efficiency somewhat, but the net improvement in program
design, resource balancing, and user convenience is often quite valuable. Of
course, if you have more than one CPU, then the operating system can dedicate
each CPU to a set of threads or even a single thread and the whole program can
run much faster. Multitasking and multithreading tend to be the most reasonable
ways to utilize multiprocessor
systems.</FONT><A NAME="_Toc375545473"></A><A NAME="_Toc408018746"></A><BR></P></DIV>
<A NAME="Heading482"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Inheriting from Thread</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The simplest way to create a thread
is to inherit from class <B>Thread</B>, which has all the wiring necessary to
create and run threads. The most important method for <B>Thread</B> is
<B>run( )</B>, which you must override to make the thread do your bidding.
Thus, <B>run( )</B> is the code that will be executed
“simultaneously” with the other threads in a
program.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The following example creates any
number of threads that it keeps track of by assigning each thread a unique
number, generated with a <B>static</B> variable. The
<A NAME="Index2448"></A><B>Thread</B>’s <B>run( )</B> method is
overridden to count down each time it passes through its loop and to finish when
the count is zero (at the point when <B>run( )</B> returns, the thread is
terminated).</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: SimpleThread.java</font>
<font color=#009900>// Very simple Threading example</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> SimpleThread <font color=#0000ff>extends</font> Thread {
<font color=#0000ff>private</font> <font color=#0000ff>int</font> countDown = 5;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -