Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Multithreading, Schemes and Mind Maps of Java Programming

In this chapter, we present all of the tools that the Java programming language provides for thread pro- gramming. We explain their use and limitations and give ...

Typology: Schemes and Mind Maps

2021/2022

Uploaded on 09/12/2022

tarquin
tarquin 🇺🇸

4.3

(15)

260 documents

1 / 113

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1
Multithreading
W
HAT
A
RE
T
HREADS
?
I
NTERRUPTING
T
HREADS
T
HREAD
P
ROPERTIES
T
HREAD
P
RIORITIES
S
ELFISH
T
HREADS
S
YNCHRONIZATION
D
EADLOCKS
U
SER
I
NTERFACE
P
ROGRAMMING
WITH
T
HREADS
U
SING
P
IPES
FOR
C
OMMUNICATION
BETWEEN
T
HREADS
Y
ou are probably familiar with
multitasking:
the ability to have more than
one program working at what seems like the same time. For example, you can
print while editing or sending a fax. Of course, unless you have a multiple-proces-
sor machine, what is really going on is that the operating system is doling out
resources to each program, giving the impression of parallel activity. This
resource distribution is possible because while you may think you are keeping the
computer busy by, for example, entering data, most of the CPU’s time will be idle.
(A fast typist takes around
1/20
of a second per character typed, after all, which is
a huge time interval for a computer.)
Multitasking can be done in two ways, depending on whether the operating sys-
tem interrupts programs without consulting with them first, or whether pro-
grams are only interrupted when they are willing to yield control. The former is
called
preemptive multitasking;
the latter is called
cooperative
(or, simply, nonpre-
emptive)
multitasking.
Windows 3.1 and Mac OS 9 are cooperative multitasking
systems, and UNIX/Linux, Windows NT (and Windows 95 for 32-bit programs),
1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b
pf3c
pf3d
pf3e
pf3f
pf40
pf41
pf42
pf43
pf44
pf45
pf46
pf47
pf48
pf49
pf4a
pf4b
pf4c
pf4d
pf4e
pf4f
pf50
pf51
pf52
pf53
pf54
pf55
pf56
pf57
pf58
pf59
pf5a
pf5b
pf5c
pf5d
pf5e
pf5f
pf60
pf61
pf62
pf63
pf64

Partial preview of the text

Download Multithreading and more Schemes and Mind Maps Java Programming in PDF only on Docsity!

Multithreading

 WHAT ARE THREADS?

 INTERRUPTING THREADS

 THREAD PROPERTIES

 THREAD PRIORITIES

 SELFISH THREADS

 SYNCHRONIZATION

 DEADLOCKS

 USER INTERFACE PROGRAMMING WITH THREADS

 USING PIPES FOR COMMUNICATION BETWEEN THREADS

You are probably familiar with multitasking: the ability to have more than

one program working at what seems like the same time. For example, you can

print while editing or sending a fax. Of course, unless you have a multiple-proces-

sor machine, what is really going on is that the operating system is doling out

resources to each program, giving the impression of parallel activity. This

resource distribution is possible because while you may think you are keeping the

computer busy by, for example, entering data, most of the CPU’s time will be idle.

(A fast typist takes around 1/20 of a second per character typed, after all, which is

a huge time interval for a computer.)

Multitasking can be done in two ways, depending on whether the operating sys-

tem interrupts programs without consulting with them first, or whether pro-

grams are only interrupted when they are willing to yield control. The former is

called preemptive multitasking; the latter is called cooperative (or, simply, nonpre-

emptive) multitasking. Windows 3.1 and Mac OS 9 are cooperative multitasking

systems, and UNIX/Linux, Windows NT (and Windows 95 for 32-bit programs),

2 Core Java

and OS X are preemptive. (Although harder to implement, preemptive multitask-

ing is much more effective. With cooperative multitasking, a badly behaved

program can hog everything.)

Multithreaded programs extend the idea of multitasking by taking it one level

lower: individual programs will appear to do multiple tasks at the same time.

Each task is usually called a thread— which is short for thread of control. Programs

that can run more than one thread at once are said to be multithreaded. Think of

each thread as running in a separate context: contexts make it seem as though

each thread has its own CPU—with registers, memory, and its own code.

So, what is the difference between multiple processes and multiple threads? The essen-

tial difference is that while each process has a complete set of its own variables,

threads share the same data. This sounds somewhat risky, and indeed it can be, as

you will see later in this chapter. But it takes much less overhead to create and destroy

individual threads than it does to launch new processes, which is why all modern

operating systems support multithreading. Moreover, inter-process communication

is much slower and more restrictive than communication between threads.

Multithreading is extremely useful in practice. For example, a browser should be

able to simultaneously download multiple images. An email program should let

you read your email while it is downloading new messages. The Java program-

ming language itself uses a thread to do garbage collection in the background—

thus saving you the trouble of managing memory! Graphical user interface (GUI)

programs have a separate thread for gathering user interface events from the host

operating environment. This chapter shows you how to add multithreading capa-

bility to your Java applications and applets.

Fair warning: multithreading can get very complex. In this chapter, we present

all of the tools that the Java programming language provides for thread pro-

gramming. We explain their use and limitations and give some simple but typ-

ical examples. However, for more intricate situations, we suggest that you

turn to a more advanced reference, such as Concurrent Programming in Java by

Doug Lea [Addison-Wesley 1999].

NOTE: In many programming languages, you have to use an external thread package to do multithreaded programming. The Java programming language builds in multi- threading, which makes your job much easier.

What Are Threads?

Let us start by looking at a program that does not use multiple threads and

that, as a consequence, makes it difficult for the user to perform several tasks

with that program. After we dissect it, we will then show you how easy it is

4 Core Java

The call to Thread.sleep does not create a new thread—sleep is a static method

of the Thread class that temporarily stops the activity of the current thread.

The sleep method can throw an InterruptedException. We will discuss this

exception and its proper handling later. For now, we simply terminate the bounc-

ing if this exception occurs.

If you run the program, the ball bounces around nicely, but it completely takes over

the application. If you become tired of the bouncing ball before it has finished its

1,000 bounces and click on the “Close” button, the ball continues bouncing anyway.

You cannot interact with the program until the ball has finished bouncing.

NOTE: If you carefully look over the code at the end of this section, you will notice the call canvas.paint(canvas.getGraphics()) inside the move method of the Ball class. That is pretty strange—normally, you’d call repaint and let the AWT worry about getting the graphics context and doing the painting. But if you try to call canvas.repaint() in this program, you’ll find out that the canvas is never repainted since the addBall method has completely taken over all processing. In the next program, where we use a separate thread to compute the ball position, we’ll again use the familiar repaint.

Obviously, the behavior of this program is rather poor. You would not want

the programs that you use behaving in this way when you ask them to do a

time-consuming job. After all, when you are reading data over a network con-

nection, it is all too common to be stuck in a task that you would really like to

interrupt. For example, suppose you download a large image and decide, after

seeing a piece of it, that you do not need or want to see the rest; you certainly

would like to be able to click on a “Stop” or “Back” button to interrupt the

loading process. In the next section, we will show you how to keep the user in

control by running crucial parts of the code in a separate thread.

Example 1–1 is the entire code for the program.

Example 1–1: Bounce.java

  1. import java.awt.*;
  2. import java.awt.event.*;
  3. (^) import java.awt.geom.*;
  4. import java.util.*;
  5. import javax.swing.*;
  6. /**
  7. Shows an animated bouncing ball.
  8. */

1 • Multithreading 5

  1. public class Bounce
  2. {
  3. public static void main(String[] args)
  4. {
  5. JFrame frame = new BounceFrame();
  6. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  7. frame.show();
  8. }
  9. }
  10. (^) /**
  11. The frame with canvas and buttons.
  12. */
  13. class BounceFrame extends JFrame
  14. {
  15. /**
  16. Constructs the frame with the canvas for showing the
  17. bouncing ball and Start and Close buttons
  18. */
  19. public BounceFrame()
  20. {
  21. setSize(WIDTH, HEIGHT);
  22. (^) setTitle("Bounce");
  23. Container contentPane = getContentPane();
  24. canvas = new BallCanvas();
  25. contentPane.add(canvas, BorderLayout.CENTER);
  26. JPanel buttonPanel = new JPanel();
  27. addButton(buttonPanel, "Start",
  28. new ActionListener()
  29. {
  30. public void actionPerformed(ActionEvent evt)
  31. {
  32. addBall();
  33. }
  34. });
  35. addButton(buttonPanel, "Close",
  36. new ActionListener()
  37. {
  38. public void actionPerformed(ActionEvent evt)
  39. {
  40. System.exit(0);
  41. }
  42. });
  43. contentPane.add(buttonPanel, BorderLayout.SOUTH);
  44. }
  45. /**
  46. Adds a button to a container.
  47. @param c the container

1 • Multithreading 7

  1. public void paintComponent(Graphics g)
  2. {
  3. super.paintComponent(g);
  4. Graphics2D g2 = (Graphics2D)g;
  5. for (int i = 0; i < balls.size(); i++)
  6. {
  7. Ball b = (Ball)balls.get(i);
  8. b.draw(g2);
  9. }
  10. }
  11. private ArrayList balls = new ArrayList();
  12. }
  13. /**
  14. A ball that moves and bounces off the edges of a
  15. component
  16. */
  17. class Ball
  18. {
  19. /**
  20. Constructs a ball in the upper left corner
  21. @c the component in which the ball bounces
  22. */
  23. public Ball(Component c) { canvas = c; }
  24. /**
  25. Draws the ball at its current position
  26. @param g2 the graphics context
  27. */
  28. public void draw(Graphics2D g2)
  29. {
  30. g2.fill(new Ellipse2D.Double(x, y, XSIZE, YSIZE));
  31. }
  32. /**
  33. Moves the ball to the next position, reversing direction
  34. if it hits one of the edges
  35. */
  36. public void move()
  37. {
  38. x += dx;
  39. y += dy;
  40. if (x < 0)
  41. {
  42. x = 0;
  43. dx = -dx;
  44. }
  45. if (x + XSIZE >= canvas.getWidth())
  46. {
  47. x = canvas.getWidth() - XSIZE;
  48. dx = -dx;

8 Core Java

  1. if (y < 0)
  2. {
  3. y = 0;
  4. dy = -dy;
  5. }
  6. if (y + YSIZE >= canvas.getHeight())
  7. {
  8. y = canvas.getHeight() - YSIZE;
  9. dy = -dy;
  10. }
  11. canvas.paint(canvas.getGraphics());
  12. }
  13. private Component canvas;
  14. private static final int XSIZE = 15;
  15. private static final int YSIZE = 15;
  16. private int x = 0;
  17. private int y = 0;
  18. private int dx = 2;
  19. private int dy = 2;
  20. }
  • static void sleep(long millis)

sleeps for the given number of milliseconds

In the previous sections, you learned what is required to split a program into

multiple concurrent tasks. Each task needs to be placed into a run method of

a class that extends Thread. But what if we want to add the run method to a

class that already extends another class? This occurs most often when we

want to add multithreading to an applet. An applet class already inherits

from JApplet, and we cannot inherit from two parent classes, so we need to

use an interface. The necessary interface is built into the Java platform. It is

called Runnable. We take up this important interface next.

Using Threads to Give Other Tasks a Chance

We will make our bouncing-ball program more responsive by running the code

that moves the ball in a separate thread.

NOTE: Since most computers do not have multiple processors, the Java virtual machine (JVM) uses a mechanism in which each thread gets a chance to run for a little while, then activates another thread. The virtual machine generally relies on the host operating sys- tem to provide the thread scheduling package.

java.lang.Thread

Parameters: millis the number of milliseconds to sleep

10 Core Java

CAUTION: Do not call the run method directly—start will call it when the thread is set up and ready to go. Calling the run method directly merely executes its contents in the same thread—no new thread is started.

Beginners are sometimes misled into believing that every method of a Thread

object automatically runs in a new thread. As you have seen, that is not true. The

methods of any object (whether a Thread object or not) run in whatever thread

they are called. A new thread is only started by the start method. That new

thread then executes the run method.

In the Java programming language, a thread needs to tell the other threads when it is

idle, so the other threads can grab the chance to execute the code in their run proce-

dures. (See Figure 1–2.) The usual way to do this is through the static sleep method.

The run method of the BallThread class uses the call to sleep(5) to indicate that

the thread will be idle for the next five milliseconds. After five milliseconds, it will

start up again, but in the meantime, other threads have a chance to get work done.

TIP: There are a number of static methods in the Thread class. They all operate on the current thread, that is, the thread that executes the method. For example, the static sleep method idles the thread that is calling sleep.

Figure 1–2: The Event Dispatch and Ball Threads

Event dispatch thread

Ball thread

move

sleep

move

sleep

start

1 • Multithreading 11

The complete code is shown in Example 1–2.

Example 1–2: BounceThread.java

  1. import java.awt.*;
  2. import java.awt.event.*;
  3. import java.awt.geom.*;
  4. import java.util.*;
  5. import javax.swing.*;
  6. /**
  7. Shows an animated bouncing ball running in a separate thread
  8. */
  9. public class BounceThread
  10. {
  11. public static void main(String[] args)
  12. {
  13. JFrame frame = new BounceFrame();
  14. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  15. frame.show();
  16. }
  17. }
  18. /**
  19. The frame with canvas and buttons.
  20. */
  21. class BounceFrame extends JFrame
  22. {
  23. /**
  24. Constructs the frame with the canvas for showing the
  25. bouncing ball and Start and Close buttons
  26. */
  27. public BounceFrame()
  28. {
  29. setSize(WIDTH, HEIGHT);
  30. setTitle("BounceThread");
  31. Container contentPane = getContentPane();
  32. canvas = new BallCanvas();
  33. contentPane.add(canvas, BorderLayout.CENTER);
  34. JPanel buttonPanel = new JPanel();
  35. addButton(buttonPanel, "Start",
  36. new ActionListener()
  37. {
  38. public void actionPerformed(ActionEvent evt)
  39. {
  40. addBall();

1 • Multithreading 13

  1. class BallThread extends Thread
  2. {
  3. /**
  4. Constructs the thread.
  5. @aBall the ball to bounce
  6. */
  7. public BallThread(Ball aBall) { b = aBall; }
  8. public void run()
  9. {
  10. try
  11. {
  12. for (int i = 1; i <= 1000; i++)
  13. {
  14. b.move();
  15. sleep(5);
  16. }
  17. }
  18. catch (InterruptedException exception)
  19. {
  20. }
  21. }
  22. private Ball b;
  23. }
  24. /**
  25. The canvas that draws the balls.
  26. */
  27. class BallCanvas extends JPanel
  28. {
  29. /**
  30. Add a ball to the canvas.
  31. @param b the ball to add
  32. */
  33. public void add(Ball b)
  34. {
  35. balls.add(b);
  36. }
  37. public void paintComponent(Graphics g)
  38. {
  39. super.paintComponent(g);
  40. Graphics2D g2 = (Graphics2D)g;
  41. for (int i = 0; i < balls.size(); i++)
  42. {

14 Core Java

  1. Ball b = (Ball)balls.get(i);
  2. b.draw(g2);
  3. }
  4. }
  5. private ArrayList balls = new ArrayList();
  6. }
  7. /**
  8. A ball that moves and bounces off the edges of a
  9. component
  10. */
  11. class Ball
  12. {
  13. /**
  14. Constructs a ball in the upper left corner
  15. @c the component in which the ball bounces
  16. */
  17. public Ball(Component c) { canvas = c; }
  18. /**
  19. Draws the ball at its current position
  20. @param g2 the graphics context
  21. */
  22. public void draw(Graphics2D g2)
  23. {
  24. g2.fill(new Ellipse2D.Double(x, y, XSIZE, YSIZE));
  25. }
  26. /**
  27. Moves the ball to the next position, reversing direction
  28. if it hits one of the edges
  29. */
  30. public void move()
  31. {
  32. x += dx;
  33. y += dy;
  34. if (x < 0)
  35. {
  36. x = 0;
  37. dx = -dx;
  38. }
  39. if (x + XSIZE >= canvas.getWidth())
  40. {
  41. x = canvas.getWidth() - XSIZE;
  42. dx = -dx;
  43. }

16 Core Java

Figure 1–3: Multiple threads

This example demonstrates a great advantage of the thread architecture in the

Java programming language. It is very easy to create any number of autonomous

objects that appear to run in parallel.

Occasionally, you may want to enumerate the currently running threads—see the

API note in the “Thread Groups” section for details.

The Runnable Interface

We could have saved ourselves a class by having the Ball class extend the

Thread class. As an added advantage of that approach, the run method has

access to the private fields of the Ball class:

class Ball extends Thread { public void run() { try { for (int i = 1; i <= 1000; i++) { x += dx; y += dy;

... canvas.repaint(); sleep(5); } } catch (InterruptedException exception)

1 • Multithreading 17

private Component canvas; private int x = 0; private int y = 0; private int dx = 2; private int dy = 2; }

Conceptually, of course, this is dubious. A ball isn’t a thread, so inheritance isn’t really

appropriate. Nevertheless, programmers sometimes follow this approach when the

run method of a thread needs to access private fields of another class. In the preced-

ing section, we’ve avoided that issue altogether by having the run method call only

public methods of the Ball class, but it isn’t always so easy to do that.

Suppose the run method needs access to private fields, but the class into which

you want to put the run method already has another superclass. Then it can’t

extend the Thread class, but you can make the class implement the Runnable

interface. As though you had derived from Thread, put the code that needs to

run in the run method. For example,

class Animation extends JApplet implements Runnable {

... public void run() { // thread action goes here } }

You still need to make a thread object to launch the thread. Give that thread a ref-

erence to the Runnable object in its constructor. The thread then calls the run

method of that object.

class Animation extends JApplet implements Runnable {

... public void start() { runner = new Thread(this); runner.start(); } ... private Thread runner; }

1 • Multithreading 19

There is no longer a way to force a thread to terminate. However, the

interrupt method can be used to request termination of a thread. That

means that the run method of a thread ought to check once in a while

whether it should exit.

public void run() {

... while ( no request to terminate && more work to do ) { do more work } // exit run method and terminate thread }

However, as you have learned, a thread should not work continuously, but it

should go to sleep or wait once in a while, to give other threads a chance to

do their work. But when a thread is sleeping, it can’t actively check whether

it should terminate. This is where the InterruptedException comes in.

When the interrupt method is called on a thread object that is currently

blocked, the blocking call (such as sleep or wait) is terminated by an

InterruptedException.

There is no language requirement that a thread that is interrupted should

terminate. Interrupting a thread simply grabs its attention. The interrupted

thread can decide how to react to the interruption by placing appropriate

actions into the catch clause that deals with the InterruptedException.

Some threads are so important that they should simply ignore their interrup-

tion by catching the exception and continuing. But quite commonly, a thread

will simply want to interpret an interruption as a request for termination.

The run method of such a thread has the following form:

public void run() { try {

... while ( more work to do ) { do more work } } catch(InterruptedException exception) { // thread was interrupted during sleep or wait } finally

20 Core Java

cleanup, if required } // exit run method and terminate thread }

However, there is a problem with this code skeleton. If the interrupt

method was called while the thread was not sleeping or waiting, then no

InterruptedException was generated. The thread needs to call the

interrupted method to find out if it was recently interrupted.

while ( !interrupted() && more work to do ) { do more work }

In particular, if a thread was blocked while waiting for input/output, the

input/output operations are not terminated by the call to interrupt. When

the blocking operation has returned, you need to call the interrupted

method to find out if the current thread has been interrupted.

NOTE: Curiously, there are two very similar methods, interrupted and isInterrupted. The interrupted method is a static method that checks whether the current thread has been interrupted. (Recall that a thread is inter- rupted because another thread has called its interrupt method.) Further- more, calling the interrupted method resets the “interrupted” status of the thread. On the other hand, the isInterrupted method is an instance method that you can use to check whether any thread has been interrupted. Calling it does not change the “interrupted” status of its argument.

It is a bit tedious that there are two distinct ways of dealing with

thread interruption—testing the “interrupted” flag and catching the

InterruptedException.

It would have been nice if methods such as sleep had been defined to

simply return with the “interrupted” flag set when an interruption occurs—

then one wouldn’t have to deal with the InterruptedException at all.

Of course, you can manually set the “interrupted” flag when an

InterruptedException is caught:

try { sleep(delay); } catch (InterruptedException exception) {