21. Apa yang dimaksud dengan thread Daemon? Apa maksudnya?
Benang Daemon, juga dikenal sebagai benang daemon, adalah benang yang menyediakan layanan umum di latar belakang saat program berjalan, dan bukan bagian integral dari program. Oleh karena itu, ketika semua thread non-Daemon berakhir, program juga akan berakhir, dan membunuh semua thread Daemon dalam prosesnya.
Sebaliknya, selama thread non-Daemon masih berjalan, program tidak akan berakhir. Metode setDaemon(true) harus dipanggil sebelum sebuah thread dimulai untuk menetapkannya sebagai thread Daemon. Catatan: Thread Daemon mengakhiri metode run() tanpa mengeksekusi klausa finally.
Thread Daemon berfungsi untuk menyediakan layanan kemudahan bagi thread lain. Seperti thread pengumpul sampah, thread Finalizer, thread pengatur waktu, dan sebagainya. Thread ini biasanya memiliki prioritas rendah dan tidak memerlukan interaksi pengguna. Thread ini dapat melakukan beberapa tugas berkala di latar belakang atau menunggu beberapa peristiwa tertentu terjadi.
Keuntungan dari Daemon thread adalah bahwa mereka dapat mengurangi beban thread utama dan meningkatkan kinerja dan stabilitas program. Kerugiannya adalah mereka tidak dapat menjamin eksekusi konten yang lengkap, yang dapat menyebabkan beberapa sumber daya tidak dapat dilepaskan atau dibersihkan. Oleh karena itu, perhatikan hal-hal berikut ini saat menggunakan thread Daemon:
Jangan mengandalkan thread Daemon untuk pekerjaan yang penting atau membutuhkan ketekunan.
Jangan memanipulasi sumber daya yang mungkin terganggu, seperti file, basis data, dll., dalam thread Daemon.
Usahakan agar thread Daemon menyelesaikan tugas saat ini atau menyimpan status sebelum keluar dari program.
22. Bagaimana cara menggunakan thread dump?, Bagaimana thread dump akan dianalisis?
Thread dump adalah alat yang digunakan untuk menganalisis aplikasi Java dengan mengetikkan perintah jstack pada baris perintah. Menentukan ID proses dari aplikasi tersebut misalnya, jstack 1234. Ini akan menghasilkan file teks yang berisi semua informasi status thread, yang dapat dianalisis dengan menggunakan editor teks atau alat lainnya.
Thread dump dapat membantu kita mendiagnosa masalah performa pada aplikasi Java. Seperti kebocoran memori, deadlock, perebutan thread, dan lain sebagainya. Informasi dalam Thread dump meliputi nama, jenis, prioritas, status, jejak stack, dll. dari thread.
Kita dapat menentukan apa yang sedang dilakukan oleh thread, apakah ada perebutan sumber daya atau menunggu. Apakah ada perulangan mati atau pemanggilan rekursif, dll. berdasarkan state dan stack trace thread.
Ada banyak cara untuk menganalisis Thread dump, yang umumnya perlu dikombinasikan dengan logika bisnis dan kode aplikasi. Beberapa langkah dan teknik yang umum adalah sebagai berikut:
Pertama, periksa jumlah total thread dan distribusi state-nya untuk melihat apakah ada kelainan atau ketidakteraturan. Seperti terlalu banyak thread, terlalu banyak blocking atau waiting thread, dan sebagainya.
Kemudian periksa jejak tumpukan setiap utas untuk mengetahui utas panas atau utas kritis. Lihat metode apa yang mereka jalankan, apakah ada operasi yang memakan waktu atau pemblokiran. Apakah ada perebutan kunci atau situasi kebuntuan, dll.
Kemudian bandingkan Thread dump yang diambil beberapa kali untuk melihat apakah ada perubahan status dan tumpukan thread, apakah ada kemajuan atau stagnasi. Apakah ada pengulangan atau pola yang sama, dll.
Terakhir, berdasarkan hasil analisis, cari penyebab masalah dan solusinya. Seperti mengoptimalkan logika kode, menyesuaikan konfigurasi parameter, dan meningkatkan sumber daya.
23. Bagaimana java mengimplementasikan komunikasi dan kolaborasi antara beberapa thread?
Java menyediakan beberapa cara untuk mengimplementasikan komunikasi dan kolaborasi antara beberapa thread, termasuk:
metode wait (), notify () dan notifyAll (): metode-metode ini merupakan metode dalam kelas Object yang dapat digunakan untuk mengimplementasikan komunikasi dan kolaborasi antar thread. metode wait () membuat thread yang sedang berjalan berada dalam kondisi menunggu hingga ada thread lain yang memanggil metode notify () atau notifyAll () untuk membangunkannya, metode notify () membangunkan thread yang sedang menunggu secara acak, dan metode notifyAll () membangunkan thread yang sedang menunggu secara acak. Metode notify () membangunkan thread yang menunggu secara acak, sedangkan metode notifyAll () membangunkan semua thread yang menunggu.
Antarmuka Lock dan Condition: Antarmuka Lock menyediakan mekanisme sinkronisasi thread yang lebih fleksibel daripada disinkronkan, yang memungkinkan penguncian yang lebih baik dan kontrol konkurensi yang lebih efisien, sedangkan antarmuka Condition menyediakan metode yang mirip dengan wait () dan notify (), yang dapat digunakan untuk komunikasi dan kolaborasi antar thread.
Kelas CountDownLatch: Kelas CountDownLatch dapat digunakan untuk mengimplementasikan kolaborasi antar thread dengan mengizinkan satu atau beberapa thread untuk menunggu thread lain menyelesaikan operasi tertentu sebelum melanjutkan eksekusi. Ketika penghitung dikurangi menjadi 0, semua thread yang menunggu akan dibangunkan.
Kelas CyclicBarrier: Kelas CyclicBarrier juga dapat digunakan untuk mengimplementasikan kolaborasi antar thread dengan mengizinkan sekelompok thread untuk menunggu satu sama lain hingga semua thread mencapai titik penghalang tertentu sebelum melanjutkan eksekusi. Ketika semua thread mencapai titik penghalang, penghalang akan terangkat secara otomatis dan semua thread dapat melanjutkan eksekusi.
Kelas Semaphore: Kelas Semaphore dapat digunakan untuk mengontrol jumlah thread yang mengakses sumber daya pada saat yang sama, dapat membatasi jumlah thread yang mengakses sumber daya pada saat yang sama, sehingga dapat menghindari perebutan sumber daya dan masalah kebuntuan. metode acquire () dari kelas Semaphore dapat digunakan untuk memperoleh sumber daya, metode release () dapat digunakan untuk melepaskan sumber daya.
Selain metode-metode di atas, java juga mendukung cara-cara berikut untuk mencapai komunikasi dan kolaborasi antara beberapa thread:
Interupsi dan Variabel Bersama: Interupsi adalah cara yang sederhana namun tidak efisien untuk memungkinkan satu thread mengirimkan sinyal ke thread lain yang mengindikasikan permintaan agar thread tersebut menghentikan apa yang sedang dilakukannya. Variabel bersama adalah cara yang umum tetapi rentan terhadap kesalahan untuk memungkinkan beberapa thread berkomunikasi dengan membaca dan menulis sepotong data bersama, tetapi perlu memastikan bahwa data tersebut terlihat dan bersifat atomik.
Pipestreaming: Pipestreaming adalah metode komunikasi berbasis aliran byte atau karakter yang menghubungkan dua thread yang berjalan di JVM yang sama sehingga satu thread mengirimkan data ke thread lainnya. Pipestreaming terdiri dari dua jenis: PipedInputStream dan PipedOutputStream (aliran byte), PipedReader dan PipedWriter (aliran karakter).
Message Queuing: Message Queuing adalah metode komunikasi berdasarkan pesan, yang dapat menghubungkan beberapa thread atau proses yang berjalan di JVM yang sama atau berbeda sehingga dapat berkomunikasi dengan mengirim dan menerima pesan. Message queue memiliki berbagai macam implementasi, seperti JMS, ActiveMQ, RabbitMQ dan lain sebagainya.
24. Apa yang terjadi jika sebuah pengecualian terjadi ketika sebuah thread sedang berjalan?
Jika sebuah thread berjalan dengan eksepsi yang tidak tertangkap, maka thread tersebut akan menghentikan eksekusinya dan melepaskan semua sumber daya yang ditempatinya. Untuk menangani situasi ini, Java menyediakan antarmuka tertanam, Thread.UncaughtExceptionHandler, yang dapat dipanggil ketika sebuah thread berhenti karena eksepsi yang tidak tertangkap.
Ketika hal ini terjadi, JVM pertama-tama memanggil metode Thread.getUncaughtExceptionHandler () untuk mendapatkan objek UncaughtExceptionHandler dari thread, dan kemudian mengoper objek thread dan objek pengecualian sebagai argumen ke metode uncaughtException () dari objek tersebut, yang menangani pengecualian. yang menangani pengecualian.
25. Apa tujuan dari metode yield dalam kelas Thread?
yield adalah metode statis yang bisa dipanggil di mana saja, tidak hanya di kelas Thread atau subkelasnya. yield memungkinkan thread yang sedang berjalan secara sukarela melepaskan penggunaan CPU, menghentikan sementara eksekusinya, dan menuju ke kondisi siap, menunggu untuk dijadwalkan kembali.
yield hanya memengaruhi thread dengan prioritas yang sama, dan tidak memengaruhi thread dengan prioritas lebih tinggi atau lebih rendah. Ini tidak berpengaruh pada thread dengan prioritas lebih tinggi atau lebih rendah.
Penting untuk dipahami bahwa metode yield hanyalah sebuah “saran” kepada penjadwal thread bahwa thread yang sedang berjalan bersedia untuk melepaskan penggunaan CPU saat ini. Namun, penjadwal thread dapat sepenuhnya mengabaikan “saran” ini. Perilaku yang tepat tergantung pada implementasi JVM dan sistem operasi.
Selain itu, yield tidak menyebabkan thread diblok, yaitu, thread masih dalam kondisi runnable setelah memanggil yield, sehingga dalam beberapa kasus, bisa saja terjadi bahwa thread mengeksekusi metode yield, dan kemudian penjadwal thread mengeluarkannya kembali untuk dieksekusi.
Metode yield sering digunakan untuk debugging dalam pemrograman multithreaded, di mana metode ini dapat membantu kita memahami dan mendemonstrasikan bagaimana penjadwal thread bekerja. Namun, yield tidak sering digunakan di lingkungan produksi dunia nyata karena perilakunya dapat sangat bervariasi di bawah JVM dan sistem operasi yang berbeda.
Sehingga sulit untuk memprediksi dan mengontrol aplikasi Java lintas platform. Lebih umum untuk menggunakan konstruksi kontrol thread yang lebih canggih seperti kata kunci tersinkronisasi dan mekanisme wait/notify, serta kelas alat dalam paket java.util.concurrent.
26. Apa yang dimaksud dengan Semaphore di Java?
Semaphore di Java adalah kelas sinkronisasi yang dapat digunakan untuk mengontrol akses bersamaan ke sumber daya tertentu. Secara konseptual, semaphore memelihara sekumpulan lisensi. Setiap thread perlu memanggil metode acquire() untuk mendapatkan lisensi sebelum mengakses sumber daya, dan jika tidak ada lisensi yang tersedia, thread akan diblokir sampai beberapa thread lain melepaskan lisensi tersebut.
Setelah menggunakan sumber daya, setiap thread perlu memanggil metode release() untuk mengembalikan lisensi, yang mungkin akan membangunkan thread yang sedang menunggu. Namun, semaphore tidak menggunakan objek lisensi yang sebenarnya, semaphore hanya menghitung jumlah lisensi yang tersedia dan melakukan tindakan yang sesuai berdasarkan jumlah tersebut.
Sinyal sering digunakan untuk membatasi jumlah thread yang dapat mengakses sumber daya tertentu (fisik atau logis) pada waktu yang sama. Sebagai contoh, berikut ini adalah kelas yang menggunakan semaphore untuk mengontrol jumlah login pengguna:
class LoginQueueUsingSemaphore { private Semaphore semaphore;
// Define a semaphore object public
LoginQueueUsingSemaphore(int slotLimit) {
// Constructor that specifies the maximum number of logins.
semaphore = new Semaphore(slotLimit);
// Initialize the semaphore
} boolean tryLogin() {
// Try the login method return
semaphore.tryAcquire();
// Invoke the semaphore's tryAcquire() method, and if there is an available license, return true and get the license, otherwise return false } void logout() {
// Logout method
semaphore.release(); // Call the signal's release() method to return a license } int availableSlots() {
// Get the number of logins currently available
return semaphore.availablePermits();
// Call the availablePermits() method of the semaphore, returning the number of licenses currently available }}
Selain metode tryAcquire(), semaphore menyediakan beberapa metode lain untuk memperoleh lisensi:
- acquire(): memperoleh lisensi, jika tidak ada lisensi yang tersedia, ia akan memblokir sampai beberapa thread lain melepaskan lisensi.
- acquire(int permits): memperoleh sejumlah izin tertentu, jika tidak ada cukup izin yang tersedia, ia akan memblokir sampai thread lain melepaskan jumlah izin yang cukup.
- acquireUninterruptibly(): memperoleh lisensi, jika tidak ada lisensi yang tersedia, ia akan memblokir hingga thread lain melepaskan lisensi, dan tidak akan merespon interupsi.
- acquireUninterruptibly(int permits): memperoleh jumlah izin yang ditentukan, jika tidak ada cukup izin yang tersedia, ia akan memblokir hingga thread lain melepaskan jumlah izin yang cukup, dan tidak akan merespons interupsi.
- tryAcquire(long timeout, unit TimeUnit): mencoba memperoleh lisensi dalam waktu yang ditentukan, jika ada thread lain dalam waktu yang ditentukan untuk melepaskan lisensi, maka kembalikan nilai true dan dapatkan lisensi; jika tidak, kembalikan nilai false.
- tryAcquire(int permits, long timeout, unit TimeUnit): mencoba memperoleh jumlah izin yang ditentukan dalam waktu yang ditentukan, jika ada thread lain yang telah melepaskan jumlah izin yang cukup dalam waktu yang ditentukan, maka kembalikan nilai true dan dapatkan izin tersebut; jika tidak, kembalikan false.
Ketika menginisialisasi semaphore, parameter keadilan opsional dapat dimasukkan. Ketika diset ke true, semaphore memastikan bahwa izin dialokasikan sesuai dengan urutan permintaan dari thread, sehingga menghindari kelaparan thread. Ketika diset ke false, semaphore tidak menjamin urutan apa pun, yang dapat mengakibatkan beberapa thread mendapatkan prioritas untuk lisensi dan beberapa thread menunggu untuk waktu yang lama.
Sinyal juga dapat digunakan untuk mengimplementasikan fungsionalitas kunci yang saling eksklusif. Jika hanya satu lisensi yang ditentukan ketika menginisialisasi semaphore, maka hanya satu thread yang bisa mendapatkan lisensi tersebut, sehingga memungkinkan akses eksklusif ke sumber daya.
Semaphore dalam hal ini juga disebut semaphore biner karena hanya memiliki dua status: dengan lisensi atau tanpa lisensi. Tidak seperti kunci, semaphore biner dapat dilepaskan oleh thread manapun, tidak harus thread yang mendapatkannya (karena semaphore tidak memiliki gagasan kepemilikan). Hal ini mungkin berguna dalam beberapa skenario khusus, seperti pemulihan kebuntuan.
27. Apa yang dimaksud dengan metode pemblokiran?
Metode pemblokiran adalah ketika sebuah program memanggil sebuah metode dan harus menunggu metode tersebut selesai dieksekusi dan mengembalikan hasilnya, di mana program tersebut tidak dapat melakukan tugas-tugas lain.
Sebagai contoh, metode accept() pada ServerSocket menunggu permintaan koneksi dari klien hingga koneksi dibuat atau waktu habis. Metode pemblokiran ditandai dengan fakta bahwa thread saat ini hang dan tidak dapat merespons peristiwa lain sampai hasilnya diperoleh. Sebaliknya, metode asinkron dan non-blocking dapat kembali sebelum tugas selesai tanpa memengaruhi eksekusi thread.
28. Bagaimana cara membuat thread yang sedang berjalan berhenti sejenak?
Kita bisa menggunakan metode sleep() dari kelas Thread untuk membuat thread berhenti sejenak untuk beberapa waktu. Ada dua versi kelebihan beban dari metode ini, satu menerima satu parameter untuk waktu jeda dalam milidetik dan yang lainnya menerima dua parameter untuk waktu jeda dalam milidetik dan nanodetik.
Perhatikan bahwa tidak ada argumen yang bernilai negatif, jika tidak, IllegalArgumentException akan dilemparkan. Memanggil metode sleep() tidak menghentikan thread, tetapi menempatkannya ke dalam kondisi pemblokiran, menunggu jumlah waktu yang ditentukan setelah itu status thread akan diubah menjadi siap, dan akan dieksekusi menurut penjadwal thread.
Namun, waktu jeda yang sebenarnya belum tentu sama persis dengan waktu yang ditentukan karena dipengaruhi oleh penjadwal utas sistem operasi dan pengatur waktu sistem. Selain itu, thread lain dapat menginterupsi thread yang sedang tidur, yang akan melemparkan InterruptedException Ketika metode sleep() dipanggil, thread tidak akan melepaskan monitor atau kunci yang sudah dipegangnya.
29. Bagaimana kita dapat memastikan bahwa thread dimana metode main() berada adalah thread dimana program Java berakhir?
Kita bisa menggunakan metode join() dari kelas Thread untuk memastikan bahwa semua thread yang dibuat oleh program berakhir sebelum metode main() keluar. Metode join() bekerja dengan membuat thread yang memanggil metode tersebut (misal, thread utama) menunggu thread yang dipanggil (misal, subthread) selesai dieksekusi sebelum melanjutkan.
Dengan cara ini, kita bisa memanggil metode join() di metode main() pada semua subthreads yang dibuat, menyebabkan thread utama keluar hanya setelah semua subthreads selesai. Contoh:
public class JoinDemo {
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1 is running");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t2 is running");
}
});
t1.start();
t2.start();
try {
// The main thread waits for t1 and t2 to finish executing.
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main thread is finished");
}}
Hasil keluaran:
t1 is runningt2 is runningmain thread is finished
Jika metode join() tidak dipanggil, utas utama dapat keluar sebelum utas anak selesai dieksekusi, yang mengakibatkan program tidak lengkap atau salah.
30. Apa yang dimaksud dengan Zero-copy?
Zero-copy adalah teknik pemrograman komputer yang tujuan utamanya adalah mengurangi jumlah salinan data, sehingga meningkatkan kinerja dan efisiensi sistem. Ketika data perlu ditransfer dari satu komponen sistem ke komponen lainnya (misalnya, dari hard drive ke memori, atau dari memori ke jaringan), data mungkin perlu disalin beberapa kali tanpa menggunakan teknologi Zero-copy.
Penyalinan data ini menghabiskan sumber daya CPU dan bandwidth memori, dan dapat mempengaruhi kinerja program. Teknik zero-copy memecahkan masalah ini dengan menghindari penyalinan data.
Berikut ini adalah tiga implementasi utama dari zero-copy:
- Akses Memori Langsung (DMA): DMA adalah teknik yang memungkinkan perangkat keras mengakses memori secara langsung tanpa melalui CPU. perangkat keras dapat membaca dan menulis memori secara langsung, sehingga menghindari penyalinan data. Ini adalah teknik umum untuk mencapai zero-copy pada tingkat perangkat keras.
- Memory-mapped (Memory-mapped IO): Dengan memetakan file atau sumber daya lain ke ruang alamat proses, penyalinan data untuk operasi baca atau tulis dapat dihindari. Ini adalah teknologi tanpa penyalinan pada tingkat sistem operasi.
- Kirim file (sendfile): sendfile adalah Linux dan beberapa sistem operasi lain menyediakan panggilan sistem, bisa di kernel langsung dari deskriptor file ke deskriptor file lain untuk menghindari penyalinan data. Ini adalah teknik untuk mencapai zero-copy pada level system call.
Teknik ini banyak digunakan di banyak aplikasi seperti sistem berkas, tumpukan jaringan dan basis data. Penggunaan zero-copy dapat secara signifikan meningkatkan kinerja dan efisiensi sistem.