Yah begitu banyak Jawaban yang baik, saya ingin menambahkan lebih banyak tentang ini. Ini akan membantu untuk memahami Extending v/s Implementing Thread
.
Memperpanjang mengikat dua file kelas sangat erat dan dapat menyebabkan beberapa sangat sulit untuk berurusan dengan kode.
Kedua pendekatan melakukan pekerjaan yang sama tetapi ada beberapa perbedaan.
Perbedaan paling umum adalah
- Ketika Anda memperluas kelas Thread, setelah itu Anda tidak dapat memperluas kelas lain yang Anda butuhkan. (Seperti yang Anda tahu, Java tidak memungkinkan mewarisi lebih dari satu kelas).
- Ketika Anda mengimplementasikan Runnable, Anda dapat menghemat ruang untuk kelas Anda untuk memperluas kelas lain di masa depan atau sekarang.
Namun, satu perbedaan signifikan antara menerapkan Runnable dan memperluas Thread adalah itu
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.
Contoh berikut akan membantu Anda memahami dengan lebih jelas
//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();
}
}
Output dari program di atas.
ImplementsRunnable : Counter : 1
ImplementsRunnable : Counter : 2
ImplementsRunnable : Counter : 3
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1
Dalam pendekatan antarmuka Runnable, hanya satu instance kelas sedang dibuat dan telah dibagikan oleh utas yang berbeda. Jadi nilai penghitung bertambah untuk setiap akses utas.
Sedangkan, pendekatan kelas Thread, Anda harus membuat turunan terpisah untuk setiap akses utas. Oleh karena itu memori yang berbeda dialokasikan untuk setiap instance kelas dan masing-masing memiliki counter yang terpisah, nilainya tetap sama, yang berarti tidak ada kenaikan akan terjadi karena tidak ada referensi objek yang sama.
Kapan menggunakan Runnable?
Gunakan antarmuka Runnable ketika Anda ingin mengakses sumber daya yang sama dari grup utas. Hindari menggunakan kelas Thread di sini, karena beberapa objek penciptaan mengkonsumsi lebih banyak memori dan itu menjadi overhead kinerja yang besar.
Kelas yang mengimplementasikan Runnable bukan thread dan hanya kelas. Agar Runnable menjadi Thread, Anda harus membuat instance Thread dan mengirimkannya sebagai target.
Dalam kebanyakan kasus, antarmuka Runnable harus digunakan jika Anda hanya berencana untuk menimpa run()
metode dan tidak ada metode Thread lainnya. Ini penting karena kelas tidak boleh disubklasifikasikan kecuali programmer berniat memodifikasi atau meningkatkan perilaku mendasar kelas.
Ketika ada kebutuhan untuk memperpanjang superclass, mengimplementasikan antarmuka Runnable lebih tepat daripada menggunakan kelas Thread. Karena kita dapat memperluas kelas lain sambil mengimplementasikan antarmuka Runnable untuk membuat utas.
Saya harap ini akan membantu!