Dari waktu yang saya habiskan dengan utas di Jawa, saya telah menemukan dua cara ini untuk menulis utas:
Dengan implements Runnable
:
public class MyRunnable implements Runnable {
public void run() {
//Code
}
}
//Started with a "new Thread(new MyRunnable()).start()" call
Atau, dengan extends Thread
:
public class MyThread extends Thread {
public MyThread() {
super("MyThread");
}
public void run() {
//Code
}
}
//Started with a "new MyThread().start()" call
Apakah ada perbedaan signifikan dalam dua blok kode ini?
java
multithreading
runnable
implements
java-threads
pengguna65374
sumber
sumber
interrupt()
. Sekali lagi, ini adalah ide, mungkin berguna dalam kasus yang tepat, namun saya tidak merekomendasikannya.Jawaban:
Ya: implementasi
Runnable
adalah cara yang disukai untuk melakukannya, IMO. Anda tidak benar-benar mengkhususkan pada perilaku utas. Anda hanya memberikannya sesuatu untuk dijalankan. Itu berarti komposisi adalah cara filosofis "lebih murni" untuk melangkah.Secara praktis , ini berarti Anda dapat mengimplementasikan
Runnable
dan memperluas dari kelas lain juga.sumber
if (numberCores > 4) myExecutor.excute(myRunnable); else myRunnable.run()
extends Thread
dan jika Anda tidak ingin threading mengapa Anda bahkan mengimplementasikanRunnable
...tl; dr: mengimplementasikan Runnable lebih baik. Namun, peringatan itu penting
Secara umum, saya akan merekomendasikan menggunakan sesuatu seperti
Runnable
daripadaThread
karena itu memungkinkan Anda untuk menjaga pekerjaan Anda hanya longgar ditambah dengan pilihan konkurensi Anda. Misalnya, jika Anda menggunakan aRunnable
dan memutuskan nanti bahwa ini sebenarnya tidak memerlukannya sendiriThread
, Anda dapat memanggil threadA.run ().Peringatan: Di sekitar sini, saya sangat tidak menyarankan penggunaan Thread mentah. Saya lebih suka menggunakan Callables dan FutureTasks (Dari javadoc: "Sebuah perhitungan asinkron yang dapat dibatalkan"). Integrasi timeout, pembatalan yang tepat, dan penggabungan thread dari dukungan konkurensi modern jauh lebih bermanfaat bagi saya daripada tumpukan Thread mentah.
Tindak lanjut: ada
FutureTask
konstruktor yang memungkinkan Anda untuk menggunakan Runnables (jika itu yang Anda paling nyaman) dan masih mendapatkan manfaat dari alat konkurensi modern. Mengutip javadoc :Jika Anda tidak membutuhkan hasil tertentu, pertimbangkan untuk menggunakan konstruksi formulir:
Jadi, jika kami ganti
runnable
dengan AndathreadA
, kami mendapatkan yang berikut:Opsi lain yang memungkinkan Anda untuk lebih dekat dengan Runnables adalah ThreadPoolExecutor . Anda dapat menggunakan metode eksekusi untuk meneruskan di Runnable untuk mengeksekusi "tugas yang diberikan suatu saat nanti."
Jika Anda ingin mencoba menggunakan kumpulan utas, fragmen kode di atas akan menjadi sesuatu seperti yang berikut (menggunakan metode pabrik Executors.newCachedThreadPool () ):
sumber
es
akan lebih baik sebagai bidang statis (atau disuntikkan) sehingga hanya akan dibuat sekali.FutureTask
secara langsung umumnya bukan yang ingin Anda lakukan.ExecutorService
s akan membuat sesuai yangFuture
untuk Anda ketika Andasubmit
seorangRunnable
/Callable
kepada mereka. Demikian juga untukScheduledExecutorService
s danScheduledFuture
ketika Andaschedule
sebuahRunnable
/Callable
.Pesan moral dalam cerita:
Mewarisi hanya jika Anda ingin menimpa beberapa perilaku.
Atau lebih tepatnya harus dibaca sebagai:
Warisan lebih sedikit, antarmuka lebih banyak.
sumber
run()
metode.java.lang.Thread
dengan menggantirun()
metode. Dalam hal ini Anda perlu menimpastart()
metode yang saya kira. Biasanya Anda hanya menggunakan kembali perilakujava.lang.Thread
dengan menyuntikkan blok eksekusi Anda kerun()
metode.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
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
Output dari program di atas.
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!
sumber
ExtendsThread et = new ExtendsThread();
Thread tc1 = new Thread(et);
tc1.start();
Thread.sleep(1000);
Thread tc2 = new Thread(et);
tc2.start();
Thread.sleep(1000);
Thread tc3 = new Thread(et);
tc3.start();
Apakah lebih jelas?Thread
bertambah juga, apakah pernyataanby extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance
itu salah? Jika tidak, lalu kasus apa yang menunjukkan hal ini?Satu hal yang saya terkejut belum disebutkan adalah implementasi
Runnable
membuat kelas Anda lebih fleksibel.Jika Anda memperpanjang utas maka tindakan yang Anda lakukan selalu akan berada di utas. Namun, jika Anda menerapkannya
Runnable
tidak harus. Anda dapat menjalankannya di utas, atau meneruskannya ke beberapa jenis layanan pelaksana, atau hanya membagikannya sebagai tugas di dalam aplikasi ulir tunggal (mungkin dijalankan di lain waktu, tetapi di utas yang sama). Opsi jauh lebih terbuka jika Anda hanya menggunakanRunnable
daripada jika Anda mengikat diriThread
.sumber
Thread
objek juga karenaThread implements Runnable
... ;-) Tetapi "terasa lebih baik" melakukan hal-hal ini denganRunnable
daripada melakukannya denganThread
!Thread
menambahkan banyak hal tambahan yang tidak Anda butuhkan, dan dalam banyak kasus tidak mau. Anda selalu lebih baik mengimplementasikan antarmuka yang sesuai dengan apa yang sebenarnya Anda lakukan.Jika Anda ingin mengimplementasikan atau memperluas kelas lain maka
Runnable
antarmuka lebih disukai, jika tidak, jika Anda tidak ingin kelas lain diperluas atau diimplementasikan makaThread
kelas lebih disukai.Perbedaan paling umum adalah
Ketika Anda
extends Thread
kelas, setelah itu Anda tidak dapat memperpanjang kelas lain yang Anda butuhkan. (Seperti yang Anda tahu, Java tidak memungkinkan mewarisi lebih dari satu kelas).Saat Anda
implements Runnable
, Anda dapat menghemat ruang untuk kelas Anda untuk memperluas kelas lain di masa depan atau sekarang.Java tidak mendukung banyak pewarisan, yang berarti Anda hanya dapat memperluas satu kelas di Jawa sehingga setelah Anda memperluas kelas Utas Anda kehilangan kesempatan dan tidak dapat memperluas atau mewarisi kelas lain di Jawa.
Dalam pemrograman berorientasi objek, memperluas kelas biasanya berarti, menambahkan fungsionalitas baru, dan memodifikasi atau meningkatkan perilaku. Jika kami tidak melakukan modifikasi apa pun di Thread, gunakan antarmuka Runnable.
Antarmuka yang dapat dijalankan mewakili Tugas yang dapat dieksekusi dengan Thread atau Pelaksana atau cara lain apa pun. jadi pemisahan yang logis dari Tugas sebagai Runnable dari Thread adalah keputusan desain yang baik.
Memisahkan tugas sebagai Runnable berarti kita dapat menggunakan kembali tugas dan juga memiliki kebebasan untuk menjalankannya dari cara yang berbeda. karena Anda tidak dapat memulai kembali Thread setelah selesai. lagi Runnable vs Thread untuk tugas, Runnable adalah pemenang.
Perancang Java mengakui hal ini dan itulah mengapa Pelaksana menerima Runnable sebagai Tugas dan mereka memiliki utas pekerja yang menjalankan tugas tersebut.
Mewarisi semua metode Thread adalah overhead tambahan hanya untuk mewakili Tugas yang dapat dilakukan dengan mudah dengan Runnable.
Atas perkenan dari javarevisited.blogspot.com
Ini adalah beberapa perbedaan penting antara Thread dan Runnable di Jawa. Jika Anda tahu ada perbedaan lain di Thread vs Runnable daripada silakan bagikan melalui komentar. Saya pribadi menggunakan Runnable over Thread untuk skenario ini dan merekomendasikan untuk menggunakan Runnable atau antarmuka Callable berdasarkan kebutuhan Anda.
Namun, perbedaannya adalah.
Saat Anda
extends Thread
kelas, masing-masing utas Anda membuat objek unik dan mengaitkannya. Saat Andaimplements Runnable
, itu berbagi objek yang sama ke beberapa utas.sumber
Sebenarnya, tidak bijaksana untuk membandingkan
Runnable
danThread
dengan satu sama lain.Keduanya memiliki ketergantungan dan hubungan multi-threading seperti halnya
Wheel and Engine
hubungan kendaraan bermotor.Saya akan mengatakan, hanya ada satu cara untuk multi-threading dengan dua langkah. Biarkan saya membuat poin saya.
Runnable:
Ketika mengimplementasikannya
interface Runnable
berarti Anda membuat sesuatu yang beradarun able
di utas yang berbeda. Sekarang membuat sesuatu yang bisa dijalankan di dalam utas (runnable di dalam utas), tidak berarti membuat Utas.Jadi kelas
MyRunnable
tidak lain adalah kelas biasa denganvoid run
metode. Dan objek itu akan menjadi beberapa objek biasa dengan hanya metoderun
yang akan dieksekusi secara normal ketika dipanggil. (kecuali jika kita melewatkan objek di utas).Thread:,
class Thread
Saya akan mengatakan kelas yang sangat istimewa dengan kemampuan memulai Thread baru yang sebenarnya memungkinkan multi-threading melaluistart()
metodenya.Mengapa tidak bijaksana untuk membandingkan?
Karena kita membutuhkan keduanya untuk multi-threading.
Untuk Multi-threading kita membutuhkan dua hal:
Jadi secara teknis dan teoritis keduanya diperlukan untuk memulai utas, satu akan berjalan dan satu akan membuatnya berjalan (Seperti
Wheel and Engine
kendaraan bermotor).Itu sebabnya Anda tidak dapat memulai utas dengan
MyRunnable
Anda harus meneruskannya ke instanceThread
.Tetapi dimungkinkan untuk membuat dan menjalankan utas hanya menggunakan
class Thread
karena KelasThread
mengimplementasikanRunnable
sehingga kita semua tahuThread
juga adaRunnable
di dalam.Akhirnya
Thread
danRunnable
saling melengkapi satu sama lain untuk multithreading bukan pesaing atau penggantian.sumber
ThreadA
tidak lagi masuk akalAnda harus mengimplementasikan Runnable, tetapi jika Anda menjalankan di Java 5 atau lebih tinggi, Anda tidak harus memulainya dengan
new Thread
tetapi menggunakan ExecutorService sebagai gantinya. Untuk detailnya lihat: Cara mengimplementasikan threading sederhana di Jawa .sumber
Saya bukan ahli, tapi saya bisa memikirkan satu alasan untuk mengimplementasikan Runnable daripada memperpanjang Thread: Java hanya mendukung satu warisan, jadi Anda hanya dapat memperluas satu kelas.
Sunting: Ini awalnya berkata "Menerapkan antarmuka membutuhkan lebih sedikit sumber daya." juga, tetapi Anda harus membuat instance Thread baru, jadi ini salah.
sumber
Saya akan mengatakan ada cara ketiga:
Mungkin ini sedikit dipengaruhi oleh penggunaan Javascript dan Actionscript 3 baru-baru ini, tetapi dengan cara ini kelas Anda tidak perlu mengimplementasikan antarmuka yang agak kabur seperti
Runnable
.sumber
Dengan rilis Java 8, sekarang ada opsi ketiga.
Runnable
adalah antarmuka fungsional , yang berarti bahwa instance dapat dibuat dengan ekspresi lambda atau referensi metode.Contoh Anda dapat diganti dengan:
atau jika Anda ingin menggunakan
ExecutorService
referensi metode dan:Ini tidak hanya jauh lebih pendek dari contoh Anda, tetapi juga datang dengan banyak keuntungan yang dinyatakan dalam jawaban lain dari menggunakan
Runnable
lebihThread
, seperti tanggung jawab tunggal dan menggunakan komposisi karena Anda tidak mengkhususkan perilaku ulir. Cara ini juga menghindari membuat kelas tambahan jika semua yang Anda butuhkan adalahRunnable
seperti yang Anda lakukan dalam contoh Anda.sumber
() -> {}
seharusnya mewakili logika kebiasaan yang dibutuhkan seseorang? Jadi akan lebih baik dikatakan() -> { /* Code here */ }
?Instantiating antarmuka memberikan pemisahan yang lebih bersih antara kode Anda dan penerapan utas, jadi saya lebih suka menerapkan Runnable dalam kasus ini.
sumber
Semua orang di sini tampaknya berpikir bahwa mengimplementasikan Runnable adalah cara untuk pergi dan saya tidak benar-benar tidak setuju dengan mereka tetapi ada juga kasus untuk memperluas Thread menurut pendapat saya, sebenarnya Anda telah menunjukkan semacam itu dalam kode Anda.
Jika Anda menerapkan Runnable maka kelas yang mengimplementasikan Runnable tidak memiliki kendali atas nama utas, itu adalah kode panggilan yang dapat mengatur nama utas, seperti:
tetapi jika Anda memperluas Thread maka Anda bisa mengelola ini di dalam kelas itu sendiri (seperti dalam contoh Anda, Anda memberi nama utas 'ThreadB'). Dalam hal ini Anda:
A) mungkin memberinya nama yang lebih berguna untuk keperluan debugging
B) memaksa agar nama itu digunakan untuk semua instance kelas itu (kecuali Anda mengabaikan fakta bahwa itu adalah utas dan lakukan yang di atas dengan itu seolah-olah itu adalah Runnable tetapi kita berbicara tentang konvensi di sini dalam hal apa pun sehingga dapat abaikan kemungkinan itu yang saya rasakan).
Misalnya, Anda bahkan dapat mengambil jejak tumpukan kreasi dan menggunakannya sebagai nama utas. Ini mungkin tampak aneh tetapi tergantung pada bagaimana kode Anda terstruktur itu bisa sangat berguna untuk keperluan debugging.
Ini mungkin tampak seperti hal kecil tetapi di mana Anda memiliki aplikasi yang sangat kompleks dengan banyak utas dan tiba-tiba 'telah berhenti' (baik karena kebuntuan atau mungkin karena cacat dalam protokol jaringan yang akan kurang jelas - atau alasan tak berujung lainnya) kemudian mendapatkan tumpukan tumpukan dari Jawa di mana semua utas disebut 'Utas-1', 'Utas-2', 'Utas-3' tidak selalu sangat berguna (tergantung pada bagaimana utas Anda berada terstruktur dan apakah Anda bisa mengetahui mana yang hanya dengan jejak tumpukan mereka - tidak selalu mungkin jika Anda menggunakan grup beberapa utas yang semuanya menjalankan kode yang sama).
Setelah mengatakan bahwa Anda tentu saja dapat juga melakukan hal di atas dengan cara yang umum dengan membuat ekstensi kelas utas yang menetapkan namanya menjadi jejak tumpukan panggilan penciptaannya dan kemudian menggunakannya dengan implementasi Runnable Anda alih-alih kelas java Thread standar (lihat di bawah) tetapi selain jejak tumpukan mungkin ada informasi spesifik lebih konteks yang akan berguna dalam nama utas untuk debugging (referensi ke salah satu dari banyak antrian atau soket yang dapat diproses misalnya dalam hal mana Anda mungkin lebih suka untuk rentangkan Thread secara khusus untuk kasing itu sehingga Anda dapat membuat kompiler memaksa Anda (atau orang lain menggunakan pustaka Anda) untuk menyampaikan info tertentu (mis. antrian / soket yang dimaksud) untuk digunakan dalam nama).
Berikut adalah contoh utas umum dengan jejak tumpukan panggilan sebagai namanya:
dan inilah contoh output yang membandingkan kedua nama:
sumber
Runnable
memang dapat mengontrol nama utas, karena utas yang menjalankan kode menurut definisi utas saat ini (dan kode apa pun yang melewati pemeriksaan keamanan memiliki kendali atas nama utas). Mengingat Anda mengabdikan setengah pos Anda ke "omg, bagaimana dengan nama utas!", Itu sepertinya masalah besar.Runnable karena:
Bahkan jika Anda tidak memerlukan semua ini sekarang, Anda mungkin di masa depan. Karena tidak ada untungnya mengganti Thread, Runnable adalah solusi yang lebih baik.
sumber
Karena ini adalah topik yang sangat populer dan jawaban yang baik tersebar di seluruh dan ditangani dengan sangat mendalam, saya merasa dibenarkan untuk mengkompilasi jawaban yang baik dari yang lain menjadi bentuk yang lebih ringkas, sehingga pendatang baru memiliki ikhtisar yang mudah di muka:
Anda biasanya memperluas kelas untuk menambah atau memodifikasi fungsionalitas. Jadi, jika Anda tidak ingin untuk menimpa setiap perilaku Thread , kemudian menggunakan Runnable.
Dalam cahaya yang sama, jika Anda tidak perlu untuk mewarisi metode benang, Anda dapat melakukannya tanpa itu biaya overhead dengan menggunakan Runnable.
Warisan tunggal : Jika Anda memperpanjang Utas Anda tidak dapat memperluas dari kelas lain, jadi jika itu yang perlu Anda lakukan, Anda harus menggunakan Runnable.
Ini adalah desain yang baik untuk logika domain terpisah dari sarana teknis, dalam arti bahwa lebih baik untuk memiliki tugas Runnable mengisolasi Anda tugas dari Anda pelari .
Anda dapat menjalankan objek Runnable yang sama beberapa kali , objek Thread, namun, hanya dapat dimulai sekali. (Mungkin alasannya, mengapa Pelaksana menerima Runnables, tetapi bukan Threads.)
Jika Anda mengembangkan tugas sebagai Runnable, Anda memiliki semua fleksibilitas cara menggunakannya sekarang dan di masa depan . Anda dapat menjalankannya secara bersamaan melalui Pelaksana tetapi juga melalui Utas. Dan Anda masih bisa menggunakan / menyebutnya secara tidak bersamaan dalam utas yang sama seperti jenis / objek biasa lainnya.
Ini membuatnya juga lebih mudah untuk memisahkan tugas-logika dan aspek konkurensi dalam pengujian unit Anda .
Jika Anda tertarik dengan pertanyaan ini, Anda mungkin juga tertarik pada perbedaan antara Callable dan Runnable .
sumber
Perbedaan antara Memperluas Thread dan Menerapkan Runnable adalah:
sumber
Ini dibahas dalam tutorial Mendefinisikan dan Memulai Thread Oracle :
Dengan kata lain, implementasi
Runnable
akan bekerja dalam skenario di mana kelas Anda memperluas kelas selainThread
. Java tidak mendukung multiple inheritance. Selain itu, perluasanThread
tidak akan mungkin dilakukan saat menggunakan beberapa API manajemen utas tingkat tinggi. Satu-satunya skenario di mana perpanjanganThread
lebih disukai adalah dalam aplikasi kecil yang tidak akan mengalami pembaruan di masa depan. Hampir selalu lebih baik untuk diterapkanRunnable
karena lebih fleksibel seiring proyek Anda tumbuh. Perubahan desain tidak akan berdampak besar karena Anda dapat mengimplementasikan banyak antarmuka di java, tetapi hanya memperluas satu kelas.sumber
Penjelasan paling sederhana adalah dengan mengimplementasikan
Runnable
kita dapat menetapkan objek yang sama ke beberapa utas dan masing-masingThread
berbagi status dan perilaku objek yang sama.Sebagai contoh, misalkan ada dua utas, utas1 menempatkan integer dalam array dan utas2 mengambil integer dari array ketika array diisi. Perhatikan bahwa agar thread2 berfungsi, perlu mengetahui status array, apakah thread1 telah mengisinya atau belum.
Menerapkan
Runnable
memungkinkan Anda untuk memiliki fleksibilitas ini untuk berbagi objek sedangkanextends Thread
membuat Anda membuat objek baru untuk setiap utas karena itu setiap pembaruan yang dilakukan oleh utas1 hilang oleh utas2.sumber
Jika saya tidak salah, ini kurang lebih mirip
Apa perbedaan antara antarmuka dan kelas abstrak?
extends menetapkan hubungan " Is A " & antarmuka menyediakan kemampuan " Memiliki ".
Lebih suka mengimplementasikan Runnable :
Lebih suka " extends Thread ":
Secara umum Anda tidak perlu mengganti perilaku Thread. Jadi mengimplementasikan Runnable lebih disukai untuk sebagian besar waktu.
Pada catatan yang berbeda, menggunakan lanjutan
ExecutorService
atauThreadPoolExecutorService
API memberikan lebih banyak fleksibilitas dan kontrol.Lihat Pertanyaan SE ini:
ExecutorService vs Casual Thread Spawner
sumber
Memisahkan kelas Thread dari implementasi Runnable juga menghindari potensi masalah sinkronisasi antara metode thread dan run (). Runnable yang terpisah umumnya memberikan fleksibilitas yang lebih besar dalam cara kode runnable direferensikan dan dieksekusi.
sumber
Itulah S dari SOLID : tanggung jawab tunggal.
Sebuah thread mewujudkan konteks yang sedang berjalan (seperti dalam konteks eksekusi: stack frame, id thread, dll.) Dari eksekusi asinkron sepotong kode. Itu bagian dari kode idealnya harus pelaksanaan yang sama, apakah sinkron atau asinkron .
Jika Anda menyatukannya dalam satu implementasi, Anda memberikan objek yang dihasilkan dua penyebab perubahan yang tidak terkait :
Jika bahasa yang Anda gunakan mendukung kelas parsial atau pewarisan berganda, maka Anda dapat memisahkan masing-masing penyebab dalam kelas supernya sendiri, tetapi itu bermuara pada sama dengan menyusun dua objek, karena set fitur mereka tidak tumpang tindih. Itu untuk teorinya.
Dalam praktiknya, secara umum, suatu program tidak perlu membawa lebih banyak kompleksitas daripada yang diperlukan. Jika Anda memiliki satu utas yang mengerjakan tugas tertentu, tanpa pernah mengubah tugas itu, mungkin tidak ada gunanya membuat kelas tugas terpisah, dan kode Anda tetap lebih sederhana.
Dalam konteks Jawa , karena fasilitas tersebut sudah ada di sana , mungkin lebih mudah untuk memulai langsung dengan
Runnable
kelas yang berdiri sendiri , dan meneruskan instance mereka keThread
(atauExecutor
) instance. Setelah terbiasa dengan pola itu, tidak sulit untuk menggunakan (atau bahkan membaca) daripada case thread runnable yang sederhana.sumber
Salah satu alasan Anda ingin mengimplementasikan antarmuka daripada memperluas kelas dasar adalah karena Anda telah memperluas beberapa kelas lainnya. Anda hanya dapat memperluas satu kelas, tetapi Anda dapat mengimplementasikan sejumlah antarmuka.
Jika Anda memperpanjang Utas, pada dasarnya Anda mencegah logika Anda dieksekusi oleh utas lain selain 'ini'. Jika Anda hanya ingin beberapa utas untuk mengeksekusi logika Anda, lebih baik menerapkan Runnable.
sumber
jika Anda menggunakan runnable Anda dapat menghemat ruang untuk memperluas ke kelas Anda yang lain.
sumber
Bisakah kita mengunjungi kembali alasan dasar kita ingin kelas kita berperilaku sebagai
Thread
? Tidak ada alasan sama sekali, kami hanya ingin menjalankan tugas, kemungkinan besar dalam mode asinkron, yang berarti bahwa pelaksanaan tugas harus bercabang dari utas utama kami dan utas utama jika selesai lebih awal, mungkin atau mungkin tidak menunggu untuk jalur bercabang (tugas).Jika ini adalah seluruh tujuannya, lalu di mana saya melihat kebutuhan Thread khusus. Ini dapat dicapai dengan mengambil RAW Thread dari Thread's System dan menugaskannya tugas kami (mungkin turunan dari kelas kami) dan hanya itu.
Jadi marilah kita mematuhi konsep OOP dan menulis kelas dari jenis yang kita butuhkan. Ada banyak cara untuk melakukan berbagai hal, melakukannya dengan cara yang benar penting.
Kami membutuhkan tugas, jadi tulis definisi tugas yang dapat dijalankan di Thread. Jadi gunakan Runnable.
Ingat selalu
implements
digunakan khusus untuk menanamkan perilaku danextends
digunakan untuk memberikan fitur / properti.Kami tidak menginginkan properti utas, sebaliknya kami ingin kelas kami berperilaku sebagai tugas yang dapat dijalankan.
sumber
Ya, Jika Anda memanggil panggilan ThreadA, maka tidak perlu memanggil metode mulai dan menjalankan metode adalah panggilan setelah memanggil kelas ThreadA saja. Tetapi jika menggunakan panggilan ThreadB maka perlu perlu utas awal untuk metode menjalankan panggilan. Jika Anda memiliki bantuan lagi, balas saya.
sumber
Saya merasa paling berguna untuk menggunakan Runnable untuk semua alasan yang disebutkan, tetapi kadang-kadang saya suka memperpanjang Thread sehingga saya dapat membuat metode menghentikan thread saya sendiri dan menyebutnya langsung pada thread yang telah saya buat.
sumber
Java tidak mendukung multiple inheritence jadi jika Anda memperluas kelas Thread maka tidak ada kelas lain yang akan diperluas.
Sebagai contoh: Jika Anda membuat applet maka ia harus memperluas kelas Applet jadi di sini satu-satunya cara untuk membuat utas adalah dengan mengimplementasikan antarmuka Runnable
sumber
Runnable
adalah antarmuka, sedangkanThread
kelas yang mengimplementasikan antarmuka ini. Dari sudut pandang desain, harus ada pemisahan yang bersih antara bagaimana tugas didefinisikan dan antara bagaimana itu dieksekusi. Yang pertama adalah tanggung jawabRunnalbe
implementasi, dan yang terakhir adalah pekerjaanThread
kelas. Dalam sebagian besar kasus, penerapanRunnable
adalah cara yang tepat untuk diikuti.sumber
Perbedaan antara Thread dan runnable. Jika kita membuat Thread menggunakan kelas Thread maka Jumlah thread sama dengan jumlah objek yang kita buat. Jika kita membuat utas dengan mengimplementasikan antarmuka yang dapat dijalankan maka kita dapat menggunakan objek tunggal untuk membuat beberapa utas. Jadi satu objek dibagi oleh beberapa Utas. Jadi itu akan memakan lebih sedikit memori
Jadi tergantung persyaratannya jika data kita tidak senstive. Jadi itu bisa dibagi antara beberapa Thread kita bisa menggunakan antarmuka Runnable.
sumber
Menambahkan dua sen saya di sini - Selalu sedapat mungkin gunakan
implements Runnable
. Di bawah ini adalah dua peringatan mengapa Anda tidak harus menggunakanextends Thread
sIdealnya Anda tidak perlu memperluas kelas Thread; yang
Thread
kelas harus dibuatfinal
. Setidaknya seperti metodethread.getId()
. Lihat diskusi ini untuk bug yang terkait dengan extendingThread
s.Mereka yang suka memecahkan teka-teki dapat melihat efek samping lain dari memperluas Thread. Kode di bawah ini akan mencetak kode yang tidak terjangkau ketika tidak ada yang memberi tahu mereka.
Silakan lihat http://pastebin.com/BjKNNs2G .
sumber