Saya benar-benar meluangkan waktu untuk mempelajari sumber yang sebenarnya, karena penasaran belaka, dan ide di baliknya cukup sederhana. Versi terbaru pada saat menulis posting ini adalah 3.2.1.
Ada buffer yang menyimpan acara yang dialokasikan sebelumnya yang akan menyimpan data untuk dibaca konsumen.
Buffer didukung oleh array flags (integer array) dengan panjangnya yang menggambarkan ketersediaan slot buffer (lihat lebih lanjut untuk detailnya). Array diakses seperti java # AtomicIntegerArray, jadi untuk tujuan penjelasan ini Anda juga dapat menganggapnya sebagai satu.
Bisa ada sejumlah produsen. Ketika produsen ingin menulis ke buffer, nomor yang panjang dihasilkan (seperti dalam memanggil AtomicLong # getAndIncrement, Disruptor sebenarnya menggunakan implementasinya sendiri, tetapi ia bekerja dengan cara yang sama). Sebut saja ini lama dihasilkan producerCallId. Dengan cara yang sama, consumerCallId dihasilkan ketika konsumen SELESAI membaca slot dari buffer. ConsumerCallId terbaru diakses.
(Jika ada banyak konsumen, panggilan dengan id terendah dipilih.)
Id ini kemudian dibandingkan, dan jika perbedaan antara keduanya lebih kecil dari sisi buffer, produser diperbolehkan untuk menulis.
(Jika producerCallId lebih besar dari consumerCallId + bufferSize baru-baru ini, itu berarti buffer sudah penuh, dan produser dipaksa untuk menunggu bus sampai suatu tempat tersedia.)
Produser kemudian diberi slot dalam buffer berdasarkan callId-nya (yang merupakan modulo bufferSize prducerCallId, tetapi karena bufferSize selalu memiliki kekuatan 2 (batas yang diberlakukan pada pembuatan buffer), operasi sebenarnya yang digunakan adalah producerCallId & (bufferSize - 1 )). Maka bebas untuk mengubah acara di slot itu.
(Algoritme yang sebenarnya sedikit lebih rumit, yang melibatkan caching consumerId baru-baru ini dalam referensi atom terpisah, untuk keperluan optimasi.)
Ketika acara itu diubah, perubahan itu "diterbitkan". Saat menerbitkan slot masing-masing dalam array bendera diisi dengan bendera yang diperbarui. Nilai flag adalah jumlah loop (producerCallId dibagi dengan bufferSize (sekali lagi karena bufferSize adalah kekuatan 2, operasi sebenarnya adalah pergeseran yang benar).
Dengan cara yang sama bisa ada sejumlah konsumen. Setiap kali konsumen ingin mengakses buffer, consumerCallId dihasilkan (tergantung pada bagaimana konsumen ditambahkan ke pengganggu atom yang digunakan dalam generasi id dapat dibagi atau terpisah untuk masing-masing). ConsumerCallId ini kemudian dibandingkan denganCallId producent terbaru, dan jika lebih rendah dari keduanya, pembaca diperbolehkan untuk maju.
(Demikian pula jika producerCallId bahkan ke consumerCallId, itu berarti bahwa buffer itu kosong dan konsumen dipaksa untuk menunggu. Cara menunggu didefinisikan oleh WaitStrategy selama pembuatan disruptor.)
Untuk konsumen individu (yang memiliki id generator sendiri), hal berikutnya yang diperiksa adalah kemampuan untuk mengkonsumsi batch. Slot dalam buffer diperiksa secara berurutan dari masing-masing ke consumerCallId (indeks ditentukan dengan cara yang sama seperti untuk produsen), ke masing-masing ke producerCallId baru-baru ini.
Mereka diperiksa dalam satu lingkaran dengan membandingkan nilai flag yang ditulis dalam array flag, dengan nilai flag yang dihasilkan untuk consumerCallId. Jika benderanya cocok, itu artinya produsen yang mengisi slot telah melakukan perubahan. Jika tidak, loop rusak, dan changeId berkomitmen tertinggi dikembalikan. Slot dari ConsumerCallId hingga diterima di changeId dapat dikonsumsi secara batch.
Jika sekelompok konsumen membaca bersama (yang memiliki id generator bersama), masing-masing hanya mengambil satu ID call, dan hanya slot untuk ID call tunggal yang diperiksa dan dikembalikan.