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
A Multithreaded Design
Let’s develop a multithreaded GUI to play the game of Pong.
Figure 14.29 shows how the game’s GUI should appear. There are three objects involved in this program: the frame, which serves as the GUI, the ball, which is represented as a blue circle in the program, and the paddle, which is represented by a red rectangle
along the right edge of the frame. What cannot be seen in this figure is that the ball moves autonomously, bouncing off the walls and paddle. The paddle’s motion is controlled by the user by pressing the up- and down-arrow keys on the keyboard.
We will develop class definitions for the ball, paddle, and the frame.
Following the example of our dot-drawing program earlier in the Chapter,
we will employ two independent threads, one for the GUI and one for the ball. Because the user will control the movements of the paddle, the frame
will employ a listener object to listen for and respond to the user’s key
presses.
Figure 14.30 provides an overview of the object-oriented design of the
Pong program. The PongFrame class is the main class. It uses instances
of the Ball and Paddle classes. PongFrame is a subclass of JFrame
and implements the KeyListener interface.
Figure 14.30: Design of the Pong
program.
This is another of the several event handlers provided in the java.awt library. This one handles KeyEvents and the KeyListener interface consists of three abstract methods: keyPressed(), keyTyped(), and keyReleased(), all
of which are associated with the act of pressing a key on the keyboard.
All three of these methods are implemented in the PongFrame class. A
key-typed event occurs when a key is pressed down. A key-release event
occurs when a key that has been pressed down is released. A key-press
event is a combination of both of these events.
The Ball class is a Thread subclass. Its data and methods are designed mainly to keep track of its motion within the program’s drawing
panel. The design strategy employed here leaves the drawing of the ball
up to the frame. The Ball thread itself just handles the movement within
the program’s drawing panel. Note that the Ball() constructor takes a
reference to the PongFrame. As we will see, the Ball uses this reference
to set the dimensions of the frame’s drawing panel. Also, as the Ball moves, it will repeatedly call the frame’s repaint() method to draw the
ball.
The Paddle class is responsible for moving the paddle up and down
along the drawing panel’s right edge. Its public methods, moveUP() and
moveDown(), will be called by the frame in response to the user pressing
the up and down arrows on the keyboard. Because the frame needs to
know where to draw the paddle, the paddle class contains several public
methods, getX(), getY(), and resetLocation(), whose tasks are to
report the paddle’s location or to adjust its location in case the frame is
resized.
The PongFrame controls the overall activity of the program. Note in
particular its ballHitsPaddle() method. This method has the task
of determining when the ball and paddle come in contact as the ball
continuously moves around in the frame’s drawing panel. As in the
ThreadedDotty example earlier in the chapter, it is necessary for the
Ball and the the frame to be implemented as separated threads so that
the frame can be responsive to the user’s key presses.