Learn

In the previous exercise, you learned that you can convert a class to run as a thread by extending the Thread class. Java allows us to make classes threaded in another way as well, by implementing the Runnable interface.

This approach is often the preferred one because you are only allowed to extend one class, and wasting it on Thread might not be beneficial to your program. Here, rather than extending the capability of the built-in Thread class, we just want to use its threading capability. Because of this, implementing the Runnable interface, which is what the Thread class does anyways, and passing the object into a new Thread object is the preferred way of implementing them. Here’s how we would implement our Factorial example by implementing Runnable instead of extending Thread.

public class Factorial implements Runnable { private int n; public Factorial(int n) { this.n = n; } public int compute(int n) { // ... the code to compute factorials } public void run() { System.out.print("Factorial of " + String.valueOf(this.n) + ":") System.out.println(this.compute(this.n)); } public static void main(String[] args) { Factorial f = new Factorial(25); Factorial g = new Factorial(10); Thread t1 = new Thread(f); Thread t2 = new Thread(f); t1.start(); t2.start(); } }

Another way of using the Runnable interface, which is even more succinct, is to use lambda expressions. This is a more modern syntax that allows you to define the run method you want to use inline, without requiring the class to implement Runnable or extend Thread. For the above example, this syntax looks like this:

public class Factorial { public int compute(int n) { // ... the code to compute factorials } public static void main(String[] args) { Factorial f = new Factorial(); // the lambda function replacing the run method new Thread(() -> { System.out.println(f.compute(25)); }).start(); // the lambda function replacing the run method new Thread(() -> { System.out.println(f.compute(10)); }).start(); } }

Behind the scenes, this syntax is still using the Runnable interface. This is because Java will translate this lambda syntax into something like:

new Thread(new Runnable() { void run() { System.out.println(f.compute(25)); } }).start();

Using the lambda expression syntax for starting threads, you can create a threaded version of your class in only a few lines!

This syntax has several benefits:

  • Your class no longer needs to extend Thread OR implement Runnable. You can make a thread from anything!
  • Your class no longer needs a constructor to store arguments! Since you can pass an argument directly into the compute function when you create your thread, we no longer need to create a separate instance of our object any time we want to perform a threaded task with it.
  • Your class is easier to read! The lambda syntax makes it so that people reading your code can immediately identify what task is being performed in your thread, without having to read your class first to find the run method.

Now, let’s try both of these methods of implementing Runnable with our FortuneTeller class.

Note: Sometimes you will see developers specifically import the Thread and Runnable classes from java.lang. This is not necessary since all Java programs naturally import the java.lang package anyways. It is often used to help with readability or remind an author to add a specific feature.

Instructions

1.

Let’s start by converting our class into one that implements Runnable instead of one that extends Thread:

  • Update the class to implement the Runnable interface, don’t forget to remove the Thread extension
  • Lastly, remember to remove the @Override annotation, as it is no longer required.
2.

Great! Now that you’ve converted the CrystalBall class to a Runnable, update FortuneTeller.java so that instead of calling .start() directly on an instance (c) of CrystalBall, it creates a new Thread t from the now Runnable version of the CrystalBall, and call .start() on that thread.

Run the code now, and you should see that this works in the exact same way as your previous code did when you extended the Thread class!

3.

Like before, you still require a new CrystalBall for every Question (q) that is asked. In practice, a single Crystal Ball should be able to think about more than one question at a time!

Now let’s try implementing lambdas. You can use the lambda expression syntax for creating Runnables to achieve this as you saw in the Factorial example.

Update CrystalBall.java class to:

  • Neither extend Thread nor implement Runnable
  • Remove the run method
  • Remove instance variable question
  • Remove the constructor
4.

Finally, update FortuneTeller.java so that instead of creating a new CrystalBall c in every iteration of the loop, it creates a CrystalBall c before the loop over the questions begins.

Then, in the loop, it should start a new Thread using the lambda expression syntax, which calls the .ask method of the CrystalBall c with the current Question q.

5.

That should be it; run the code to see how the threaded FortuneTeller program works! Feel free to tweak it further to see how you can make the output easier to understand.

Take this course for free

Mini Info Outline Icon
By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.

Or sign up using:

Already have an account?