Dapatkah seseorang membantu saya untuk memahami apa itu Java CountDownLatch
dan kapan menggunakannya?
Saya tidak punya ide yang jelas tentang cara kerja program ini. Seperti yang saya pahami ketiga utas mulai sekaligus dan setiap utas akan memanggil CountDownLatch setelah 3000ms. Jadi hitung mundur akan berkurang satu per satu. Setelah kait menjadi nol program mencetak "Selesai". Mungkin cara saya memahami itu salah.
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Processor implements Runnable {
private CountDownLatch latch;
public Processor(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
System.out.println("Started.");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
}
// ------------------------------------------------ -----
public class App {
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(3); // coundown from 3 to 0
ExecutorService executor = Executors.newFixedThreadPool(3); // 3 Threads in pool
for(int i=0; i < 3; i++) {
executor.submit(new Processor(latch)); // ref to latch. each time call new Processes latch will count down by 1
}
try {
latch.await(); // wait until latch counted down to 0
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Completed.");
}
}
Jawaban:
Ya, Anda mengerti dengan benar.
CountDownLatch
bekerja pada prinsip kait, utas utama akan menunggu sampai gerbang terbuka. Satu utas menunggu n utas, ditentukan saat membuatCountDownLatch
.Setiap utas, biasanya utas utama aplikasi, yang
CountDownLatch.await()
akan menunggu hingga hitungan mencapai nol atau terputus oleh utas lainnya. Semua utas lainnya diharuskan untuk menghitung mundur dengan meneleponCountDownLatch.countDown()
setelah selesai atau siap.Segera setelah hitungan mencapai nol, utas menunggu berlanjut. Salah satu kelemahan / kelebihan
CountDownLatch
adalah tidak dapat digunakan kembali: sekali hitungan mencapai nol Anda tidak dapat menggunakanCountDownLatch
lagi.Edit:
Gunakan
CountDownLatch
ketika satu utas (seperti utas utama) mengharuskan untuk menunggu satu atau lebih utas selesai, sebelum dapat melanjutkan pemrosesan.Contoh klasik penggunaan
CountDownLatch
di Jawa adalah aplikasi Java inti sisi server yang menggunakan arsitektur layanan, di mana beberapa layanan disediakan oleh banyak utas dan aplikasi tidak dapat memulai pemrosesan hingga semua layanan mulai berhasil.Pertanyaan PS OP memiliki contoh yang cukup jelas sehingga saya tidak memasukkan satu pun.
sumber
One thread waits for n number of threads specified while creating CountDownLatch in Java
. Jika Anda membutuhkan mekanisme seperti itu, maka lebih bijaksana untuk menggunakannyaCyclicBarrier
. Perbedaan konseptual mendasar antara kedua, seperti yang diberikan dalamJava concurrency in Practice
adalah:Latches are for waiting for events; barriers are for waiting for other threads
.cyclicBarrier.await()
masuk ke keadaan memblokir.CountDownLatch
di Java adalah jenis sinkronisasi yang memungkinkan seseorangThread
untuk menunggu satu atau lebihThread
sebelum mulai diproses.CountDownLatch
bekerja pada prinsip kait, utas akan menunggu sampai gerbang terbuka. Satu utas menunggun
jumlah utas yang ditentukan saat membuatCountDownLatch
.misalnya
final CountDownLatch latch = new CountDownLatch(3);
Di sini kita mengatur penghitung ke 3.
Utas apa pun, biasanya utas utama aplikasi, yang
CountDownLatch.await()
akan menunggu hingga hitungan mencapai nol atau terganggu oleh yang lainThread
. Semua utas lainnya diharuskan untuk melakukan hitung mundur dengan meneleponCountDownLatch.countDown()
setelah selesai atau siap untuk pekerjaan itu. segera setelah hitungan mencapai nol,Thread
menunggu mulai berjalan.Di sini perhitungannya dikurangi dengan
CountDownLatch.countDown()
metode.Metode
Thread
yang memanggilawait()
metode akan menunggu sampai hitungan awal mencapai nol.Untuk menghitung nol utas lainnya perlu memanggil
countDown()
metode. Setelah hitungan menjadi nol utas yang dipanggilawait()
metode akan dilanjutkan (mulai eksekusi).Kerugiannya
CountDownLatch
adalah itu tidak dapat digunakan kembali: sekali hitungan menjadi nol maka tidak lagi dapat digunakan.sumber
new CountDownLatch(3)
karena kita memiliki 3 utas dari yangnewFixedThreadPool
ditentukan?NikolaB menjelaskannya dengan sangat baik, Namun contoh akan sangat membantu untuk dipahami, Jadi di sini adalah salah satu contoh sederhana ...
sumber
Ini digunakan ketika kita ingin menunggu lebih dari satu utas untuk menyelesaikan tugasnya. Ini mirip dengan bergabung dalam utas.
Di mana kita bisa menggunakan CountDownLatch
Pertimbangkan skenario di mana kami memiliki persyaratan di mana kami memiliki tiga utas "A", "B" dan "C" dan kami ingin memulai utas "C" hanya jika utas "A" dan "B" menyelesaikan atau menyelesaikan sebagian tugas mereka.
Ini dapat diterapkan pada skenario IT dunia nyata
Pertimbangkan skenario di mana manajer membagi modul antara tim pengembangan (A dan B) dan dia ingin menugaskannya ke tim QA untuk pengujian hanya ketika kedua tim menyelesaikan tugas mereka.
Output dari kode di atas adalah:
Tugas yang ditugaskan untuk pengembangan tim devB
Tugas yang diberikan kepada pengembang tim pengembang
Tugas diselesaikan oleh tim pengembang devB
Tugas diselesaikan oleh pengembang tim pengembang
Tugas yang diberikan kepada tim QA
Tugas diselesaikan oleh tim QA
Di sini menunggu () metode menunggu flag countdownlatch menjadi 0, dan countDown () metode menurunkan flag countdownlatch oleh 1.
Batasan BERGABUNG: Contoh di atas juga dapat dicapai dengan BERGABUNG, tetapi BERGABUNG tidak dapat digunakan dalam dua skenario:
sumber
CoundDownLatch memungkinkan Anda untuk membuat utas menunggu sampai semua utas lainnya selesai dengan eksekusi mereka.
Kode semu dapat berupa:
sumber
Salah satu contoh yang baik kapan harus menggunakan sesuatu seperti ini adalah dengan Java Simple Serial Connector, mengakses port serial. Biasanya Anda akan menulis sesuatu ke port, dan secara asinkron, pada utas lainnya, perangkat akan merespons pada SerialPortEventListener. Biasanya, Anda ingin berhenti setelah menulis ke port untuk menunggu respons. Menangani kunci utas untuk skenario ini secara manual sangat sulit, tetapi menggunakan Countdownlatch mudah. Sebelum Anda berpikir Anda bisa melakukannya dengan cara lain, berhati-hatilah dengan kondisi balapan yang tidak pernah Anda pikirkan !!
Kodesemu:
sumber
Jika Anda menambahkan beberapa debug setelah panggilan Anda ke latch.countDown (), ini dapat membantu Anda memahami perilakunya dengan lebih baik.
Output akan menunjukkan Count dikurangi. 'Hitungan' ini secara efektif adalah jumlah tugas Runnable (objek Prosesor) yang Anda mulai terhadap countDown () yang belum dipanggil dan karenanya diblokir utas utama pada panggilannya ke latch.await ().
sumber
Dari dokumentasi oracle tentang CountDownLatch :
A
CountDownLatch
diinisialisasi dengan jumlah yang diberikan. Theawait
metode memblokir sampai mencapai jumlah saat ini nol karena doa daricountDown()
metode, setelah semua thread menunggu dilepaskan dan setiap doa selanjutnya pengembalian Tunggulah segera. Ini adalah fenomena sekali pakai - penghitungan tidak dapat diatur ulang.Sebuah
CountDownLatch
diinisialisasi dengan hitungan satu servis sebagai sederhana on / off kait, atau gerbang: semua thread yang memanggil menunggu menunggu di pintu gerbang sampai dibuka oleh thread memanggil Countdown ().Sebuah
CountDownLatch
diinisialisasi ke N dapat digunakan untuk membuat satu thread menunggu sampai N benang telah menyelesaikan beberapa tindakan, atau beberapa tindakan telah selesai N kali.Jika jumlah saat ini adalah nol maka metode ini segera kembali.
Jika jumlah saat ini lebih besar dari nol maka akan dikurangi. Jika jumlah baru adalah nol maka semua utas menunggu diaktifkan kembali untuk tujuan penjadwalan utas.
Penjelasan contoh Anda.
Anda telah menetapkan jumlah sebagai 3 untuk
latch
variabelAnda telah membagikan ini
latch
ke utas Pekerja:Processor
Runnable
contohProcessor
telah diserahkan kepadaExecutorService
executor
Utas utama (
App
) sedang menunggu hitungan menjadi nol dengan pernyataan di bawah iniProcessor
thread tidur selama 3 detik dan kemudian menurunkan nilai hitung denganlatch.countDown()
Pertama
Process
virtual akan mengubah jumlah kait menjadi 2 setelah selesai karenalatch.countDown()
.Mesin
Process
virtual kedua akan mengubah jumlah kait sebagai 1 setelah selesai karenalatch.countDown()
.Mesin
Process
virtual ketiga akan mengubah jumlah kait sebagai 0 setelah selesai karenalatch.countDown()
.Zero count on latch menyebabkan
App
keluarnya utas utamaawait
Program aplikasi mencetak hasil ini sekarang:
Completed
sumber
Contoh dari Java Doc ini membantu saya memahami konsep dengan jelas:
Interpretasi visual:
Jelas,
CountDownLatch
memungkinkan satu utas (di siniDriver
) menunggu sampai sekelompok utas yang berjalan (di siniWorker
) selesai dengan eksekusi mereka.sumber
Seperti disebutkan dalam JavaDoc ( https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html ), CountDownLatch adalah alat bantu sinkronisasi, diperkenalkan di Java 5. Di sini sinkronisasi tidak berarti membatasi akses ke bagian kritis. Melainkan tindakan pengurutan dari utas yang berbeda. Jenis sinkronisasi yang dicapai melalui CountDownLatch mirip dengan yang dimiliki Join. Asumsikan ada utas "M" yang perlu menunggu utas pekerja lain "T1", "T2", "T3" untuk menyelesaikan tugasnya Sebelum ke Java 1.5, cara ini bisa dilakukan adalah, M menjalankan kode berikut
Kode di atas memastikan bahwa utas M melanjutkan pekerjaannya setelah T1, T2, T3 menyelesaikan pekerjaannya. T1, T2, T3 dapat menyelesaikan pekerjaan mereka dalam urutan apa pun. Hal yang sama dapat dicapai melalui CountDownLatch, di mana T1, T2, T3 dan thread M berbagi objek CountDownLatch yang sama.
"M" meminta:
countDownLatch.await();
sedangkan "T1", "T2", "T3" melakukannya
countDownLatch.countdown();
Salah satu kelemahan dengan metode join adalah bahwa M harus tahu tentang T1, T2, T3. Jika ada T4 pekerja baru yang ditambahkan kemudian, maka M juga harus menyadarinya. Ini bisa dihindari dengan CountDownLatch. Setelah implementasi, urutan tindakannya adalah [T1, T2, T3] (urutan T1, T2, T3 bisa jadi tetap) -> [M]
sumber
Contoh waktu nyata terbaik untuk countDownLatch dijelaskan dalam tautan ini CountDownLatchExample
sumber
sumber