There are multiple ways to implement threading in Java. The first that we will try involves extending the Thread class. In Java, there is a built-in class that handles threads: java.lang.Thread. To create a thread, you create a class that extends the built-in Thread class and then overrides its public void run()
method. Beyond these two requirements, the rest of your class can have anything you want in it!
The public void run()
method that you override performs the actual work that your thread should be responsible for. This may be performing a long-running computation, calling out to another application or service, or other tasks that involve some waiting.
When you’ve defined your class in this way, you can then create an instance of your class in any other part of your program and call .start()
on the instance to trigger the thread’s execution.
Here’s an example of a sequential program in Java that computes the meaning of life:
public class HugeProblemSolver { private static void solveComputation() { // Solves random computation // Takes anywhere from 1 second to 10 minutes System.out.println("The answer is: 42"); } public static void main(String[] args) { HugeProblemSolver.solveComputation(); HugeProblemSolver.solveComputation(); } }
In this program, we will only see the answer to the second question after the first question has been answered. A threaded solution would allow us to start the computations at the same time, and receive the answers as soon as they are available.
Let’s take a look at the threaded approach:
public class HugeProblemSolver extends Thread { private static void solveComputation() { // Solves random computation // Takes anywhere from 1 second to 10 minutes } @Override public void run() { solveComputation(); System.out.println("The answer is: 42"); } public static void main(String[] args) { HugeProblemSolver m1 = new HugeProblemSolver(); HugeProblemSolver m2 = new HugeProblemSolver(); m1.start(); m2.start(); } }
Now, you can see that all that changed was:
- Extended the
Thread
Class - Created and Overrode a
.run()
method fromThread
- Instantiated
HugeProblemSolver
and called.start()
which signifies to start a new thread and search in the class for the.run()
method to execute.
Now, both Thread
s we created are working on solving their own problems simultaneouly. Whichever one finishes first will print to the console first, no need to wait on sequential order.
Let’s see how we can implement this in our CrystalBall
class.
Instructions
The CrystalBall “thinks” for a given amount of time, based on question complexity when it is “asked a question”. This is where we want to allow multiple threads to start concurrently.
Update CrystalBall.java to extend the Thread
class.
You may have noticed that the CrystalBall
class does not have a constructor! Passing arguments to classes implemented as threads requires a constructor because there is no way to provide any arguments to the .start()
method. All the information that a threaded class requires to do its work should be supplied via its constructor. For this class, this information is the Question
.
- Create a private instance variable
question
, of typeQuestion
in the class, it will be used to store the question that is being asked of the Crystal Ball when we finish our multithreading approach. - Create a constructor for the
CrystalBall
class that accepts aQuestion question
. Use the constructor to initialize the instance variable you just created.
Now we need to @Override
the Thread
class’s .run()
method.
- Start by declaring the
.run()
method and adding the required@Override
annotation. - Inside
.run()
, call.ask()
, passing in the instance variable you just created,this.question
.
Now let’s update FortuneTeller.java to reflect our changes and start our threads:
- Update the
CrystalBall c
‘s constructor in theforEach
loop to now pass in theQuestion q
. - Instead of calling
.ask(q)
on the instance ofCrystalBall c
, change it to.start()
. We already passed in the question in the constructor, so this is all we need to do to start our threads.
You’ve done it! Try running the newly threaded FortuneTeller
program to see how much faster the program completes, now that the CrystalBall
class has been threaded.
- use
javac *.java
to compile all java files - use
java FortuneTeller
to run the program