Bene, tante buone risposte, voglio aggiungere altro su questo. Questo aiuterà a capire Extending v/s Implementing Thread
.
Extends lega i file di due classi molto da vicino e può causare un po 'di difficoltà nel gestire il codice.
Entrambi gli approcci fanno lo stesso lavoro ma ci sono state alcune differenze.
La differenza più comune è
- Quando estendi la classe Thread, dopo non puoi estendere nessuna altra classe richiesta. (Come sai, Java non consente di ereditare più di una classe).
- Quando si implementa Runnable, è possibile risparmiare spazio per la classe per estendere qualsiasi altra classe in futuro o ora.
Tuttavia, una differenza significativa tra l'implementazione di Runnable e l'estensione di Thread è quella
by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.
L'esempio seguente ti aiuterà a capire più chiaramente
//Implement Runnable Interface...
class ImplementsRunnable implements Runnable {
private int counter = 0;
public void run() {
counter++;
System.out.println("ImplementsRunnable : Counter : " + counter);
}
}
//Extend Thread class...
class ExtendsThread extends Thread {
private int counter = 0;
public void run() {
counter++;
System.out.println("ExtendsThread : Counter : " + counter);
}
}
//Use the above classes here in main to understand the differences more clearly...
public class ThreadVsRunnable {
public static void main(String args[]) throws Exception {
// Multiple threads share the same object.
ImplementsRunnable rc = new ImplementsRunnable();
Thread t1 = new Thread(rc);
t1.start();
Thread.sleep(1000); // Waiting for 1 second before starting next thread
Thread t2 = new Thread(rc);
t2.start();
Thread.sleep(1000); // Waiting for 1 second before starting next thread
Thread t3 = new Thread(rc);
t3.start();
// Creating new instance for every thread access.
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();
}
}
Uscita del programma sopra.
ImplementsRunnable : Counter : 1
ImplementsRunnable : Counter : 2
ImplementsRunnable : Counter : 3
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1
Nell'approccio dell'interfaccia Runnable, viene creata solo un'istanza di una classe ed è stata condivisa da thread diversi. Quindi il valore del contatore viene incrementato per ogni accesso al thread.
Considerando che, l'approccio della classe Thread, è necessario creare un'istanza separata per ogni accesso al thread. Quindi memoria diversa viene allocata per ogni istanza di classe e ognuna ha un contatore separato, il valore rimane lo stesso, il che significa che non si verificherà alcun incremento poiché nessuno dei riferimenti all'oggetto è uguale.
Quando usare Runnable?
Utilizzare l'interfaccia Runnable quando si desidera accedere alle stesse risorse dal gruppo di thread. Evita di usare la classe Thread qui, perché la creazione di più oggetti consuma più memoria e diventa un grande sovraccarico di prestazioni.
Una classe che implementa Runnable non è un thread e solo una classe. Perché un Runnable diventi un thread, è necessario creare un'istanza di thread e passare se stesso come destinazione.
Nella maggior parte dei casi, l'interfaccia Runnable deve essere utilizzata se si prevede di sovrascrivere il run()
metodo e nessun altro metodo Thread. Questo è importante perché le classi non dovrebbero essere sottoclassate a meno che il programmatore non intenda modificare o migliorare il comportamento fondamentale della classe.
Quando è necessario estendere una superclasse, l'implementazione dell'interfaccia Runnable è più appropriata rispetto all'utilizzo della classe Thread. Perché possiamo estendere un'altra classe mentre implementiamo l'interfaccia Runnable per creare un thread.
Spero che questo possa aiutare!