Threads and Concurrent Programming
Threads may be seen as methods that execute at "the same time" as other methods. Normally, we think sequentially when writing a computer program. From this perspective, only one thing executes at a time. However, with today's multi-core processors, it is possible to literally have several things going on at the very same time while sharing the same memory. There are lots of ways that this is done in the real world, and this chapter goes over them in a way that you can apply to your own projects.
14.7 CASE STUDY: The Game of Pong
Animating the Bouncing Ball
Computer animation is accomplished by repeatedly drawing, erasing,
and re-drawing an object at different locations on the drawing panel.
The frame’s paint() method is used for drawing the ball and the paddle at their current locations. The paint() method is never called directly. Rather, it is called automatically after the constructor method
PongFrame(), when the program is started. It is then invoked indirectly
by the program by calling the repaint() method, which is called in the
run() method of the Ball class. The reason that paint() is called indirectly is because Java needs to pass it the frame’s current Graphics
object. Recall that in Java all drawing is done using a Graphics object.
In order to animate the bouncing ball, we first erase the current image
of the ball, then we draw the ball in its new location. We also draw the
paddle in its current location. These steps are carried out in the frame’s
paint() method. First, the drawing area is cleared by painting its rectangle in the background color. Then the ball and paddle are painted at
their current locations. Note that before painting the paddle, we first call
its resetLocation() method. This causes the paddle to be relocated in
case the user has resized the frame’s drawing area. There is no need to
do this for the ball because the ball’s drawing area is updated within the
Ball.move() method every time the ball is moved.
One problem with computer animations of this sort is that the repeated
Double buffering drawing and erasing of the drawing area can cause the screen to flicker.
In some drawing environments a technique known as double buffering
is used to reduce the flicker. In double buffering, an invisible, off-screen,
buffer is used for the actual drawing operations and it is then used to
replace the visible image all at once when the drawing is done. Fortunately, Java’s Swing components, including JApplet and JFrame, perform an automatic form of double buffering, so we needn’t worry about
it. Some graphics environments, including Java’s AWT environment, do
not perform double buffering automatically, in which case the program
itself must carry it out.
Like the other examples in this chapter, the game of Pong provides a
simple illustration of how threads are used to coordinate concurrent actions in a computer program. As most computer game fans will realize,
most modern interactive computer games utilize a multithreaded design.
The use of threads allows our interactive programs to achieve a responsiveness and sophistication that is not possible in single-threaded programs. One of the great advantages of Java is that it simplifies the use of
threads, thereby making thread programming accessible to programmers.
However, one of the lessons that should be drawn from this chapter is
that multithreaded programs must be carefully designed in order to work
effectively.
SELF-STUDY EXERCISE
EXERCISE 14.12 Modify the PongFrame program so that it contains a
second ball that starts at a different location from the first ball.