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
Implementation of the Pong Program
We begin our discussion of the program’s implementation with the
Paddle class implementation (Fig. 14.31).
Class constants, HEIGHT and WIDTH are used to define the size of the
Paddle, which is represented on the frame as a simple rectangle. The
frame will use the Graphics.fillRect() method to draw the paddle:
Note how the frame uses the paddle’s getX() and getY() methods to
get the paddle’s current location.
The class constants DELTA and BORDER are used to control the paddle’s
movement. DELTA represents the number of pixels that the paddle moves
on each move up or down, and BORDER is used with gameAreaHeight
to keep the paddle within the drawing area. The moveUp() and
moveDown() methods are called by the frame each time the user presses
an up- or down-arrow key. They simply change the paddle’s location by
DELTA pixels up or down.
The Ball class (Fig. 14.32) uses the class constant SIZE to determine
the size of the oval that represents the ball, drawn by the frame as follows:
As with the paddle, the frame uses the ball’s getX() and getY() method
to determine the ball’s current location.
Unlike the paddle, however, the ball moves autonomously. Its run()
method, which is inherited from its Thread superclass, repeatedly moves
the ball, draws the ball, and then sleeps for a brief interval (to slow down
the speed of the ball’s apparent motion). The run() method itself is quite
simple because it consists of a short loop. We will deal with the details of
how the ball is painted on the frame when we discuss the frame itself.
The most complex method in the Ball class is the move() method.
This is the method that controls the ball’s movement within the boundaries of the frame’s drawing area. This method begins by moving the
ball by one pixel left, right, up, or down by adjusting the values of its
locationX and locationY coordinates:
The directionX and directionY variables are set to either +1 or 1,
depending on whether the ball is moving left or right, up or down. After
the ball is moved, the method uses a sequence of if statements to check
whether the ball is touching one of the walls or the paddle. If the ball is
in contact with the top, left, or bottom walls or the paddle, its direction
is changed by reversing the value of the directionX or directionY
variable. The direction changes depend on whether the ball has touched
a horizontal or vertical wall. When the ball touches the right wall, having
missed the paddle, it passes through the right wall and re-emerges from
the left wall going in the same direction.
Note how the frame method, ballHitsPaddle() is used to determine whether the ball has hit the paddle. This is necessary because only
the frame knows the locations of both the ball and the paddle.