Yes, Thread
implements Runnable
.
As the API references states runnable interface is designed to provide a common protocol for objects that wish to execute code while they are active.
You are getting confused because there are two ways of making this kind of concurrency in Java:
- you can extend a
Thread
class overriding the default run
method, then invoke the thread in a way similar to new MyThread().start()
- you can write a class that implements the
Runnable
interface and start it in a similar way: new Thread(new MyRunnable()).start()
These approaches are IDENTICAL. Infact the run
method of class Thread
normally calls the run
method of Runnable
object attached to the thread if any, otherwise it returns.
What is the need of having a Runnable
interface? It's useful because it declares a protocol to let classes be considered with specific characteristics.
This is the same thing of Comparable
interface or Serializable
interface, but here you effectively have a method to override (public void run()
) while for example Serializable
is just a trait you give to your class.
A final example is the fact that TimerTask
implements Runnable
. TimerTask
is used together with Timer
class to execute delayed or periodic tasks, so it makes sense that a timertask is also runnable, so that Timer can launch tasks using exactly that method.
EDIT: since you seem confused by the usefulness of an interface you have to think that: Java is a statically typed language. What does it mean? It means that it needs to know everything about a type during compilation to be able to guarantee that not run-time type error will ever be thrown.
Ok, now suppose that Java API supports a hipotetically class to draw shapes. So you can write your own classes for the shapes and then feed them to this class (let's call it ShapeDrawer
).
ShapeDrawer
needs to know how to draw the shapes you pass to it and the only way to be sure of it is to decide that every Shape
object must have a method called public void drawMe()
, so that ShapeDrawer
can call this method on every Shape
you attach to it without knowing anything more than this.
So you declare an interface
public interface Shape
{
public void drawMe();
}
that classes can use to be considered a Shape
. And if a class is a Shape
you can pass it to your ShapeDrawer
class with no problem:
class ShapeDrawer
{
public void addShape(Shape shape) { ... }
public void drawShapes()
{
for (Shape s : shapes)
s.drawMe();
}
}
So that compiler is happy because when adding shapes you add classes that implements Shape
, you class knows exactly how to draw such shapes and developers are happy because you separated the common protocol of an object from their specific implementations.
It's a sort of contract, if you want a Triangle
class that is able to be drawn by ShapeManager
you have to the declare that method, so that you can call for example
shapeDrawerInstance.addShape(new Triangle())