Here's what the javadoc states
There are two ways to create a new thread of execution. One is to
declare a class to be a subclass of Thread. This subclass should
override the run method of class Thread. An instance of the subclass
can then be allocated and started. For example, a thread that computes
primes larger than a stated value could be written as follows:
The other way to create a thread is to declare a class that implements
the Runnable interface. That class then implements the run method. An
instance of the class can then be allocated, passed as an argument
when creating Thread, and started. The same example in this other
style looks like the following:
So the two ways
public class MyThread extends Thread {
// overriden from Runnable, which Thread implements
public void run() {
...
}
}
...
MyThread thread = new MyThread();
thread.start();
Or
public class MyRunnable implements Runnable{
public void run() {
...
}
}
...
Thread thread = new Thread(new MyRunnable());
thread.start();
Your counter
field is an instance field.
In your first case, each of the objects created here
ExtendsThread tc1 = new ExtendsThread();
tc1.start();
Thread.sleep(1000); // Waiting for 1 second before starting next thread
ExtendsThread tc2 = new ExtendsThread();
tc2.start();
Thread.sleep(1000); // Waiting for 1 second before starting next thread
ExtendsThread tc3 = new ExtendsThread();
tc3.start();
will have their own copy (that's how instance variables work). So when you start each thread, each one increments its own copy of the field.
In your second case, you are using your Thread
sub class as a Runnable
argument to the Thread
constructor.
ExtendsThread extendsThread = new ExtendsThread();
Thread thread11 = new Thread(extendsThread);
thread11.start();
Thread.sleep(1000);
Thread thread12 = new Thread(extendsThread);
thread12.start();
Thread.sleep(1000);
Thread thread13 = new Thread(extendsThread);
thread13.start();
Thread.sleep(1000);
It is the same ExtendsThread
object that you pass, so its counter
field gets incremented by all threads. It's pretty much equivalent to your previous usage of ImplementsRunnable
.
To add from the comments:
First thing to understand is that the Thread
class implements Runnable
, so you can use a Thread
instance anywhere you can use Runnable
. For example,
new Thread(new Thread()); // won't do anything, but just to demonstrate
When you create a Thread
with
new Thread(someRunnable);
and start it, the thread calls the given Runnable
instance's run()
method. If that Runnable
instance happens to also be an instance of Thread
, so be it. That doesn't change anything.
When you create a custom thread like
new ExtendsThread();
and start it, it calls run()
on itself.