Tôi thực sự đã dành thời gian để nghiên cứu nguồn thực tế, vì tò mò và ý tưởng đằng sau nó khá đơn giản. Phiên bản gần đây nhất tại thời điểm viết bài này là 3.2.1.
Có một bộ đệm lưu trữ các sự kiện được phân bổ trước sẽ giữ dữ liệu cho người tiêu dùng đọc.
Bộ đệm được hỗ trợ bởi một mảng các cờ (mảng số nguyên) có độ dài mô tả sự sẵn có của các vị trí đệm (xem thêm để biết chi tiết). Mảng được truy cập như java # AtomicIntegerArray, vì vậy với mục đích khám phá này, bạn cũng có thể giả sử nó là một.
Có thể có bất kỳ số lượng các nhà sản xuất. Khi nhà sản xuất muốn ghi vào bộ đệm, một số dài được tạo ra (như khi gọi AtomicLong # getAndIncrement, Disruptor thực sự sử dụng triển khai riêng của mình, nhưng nó hoạt động theo cách tương tự). Chúng ta hãy gọi điều này được tạo ra từ lâu là nhà sản xuấtCallId. Theo cách tương tự, ConsumerCallId được tạo khi người tiêu dùng KẾT THÚC đọc một vị trí từ bộ đệm. Người tiêu dùng gần đây nhất được truy cập.
(Nếu có nhiều người tiêu dùng, cuộc gọi có id thấp nhất sẽ được chọn.)
Các id này sau đó được so sánh và nếu sự khác biệt giữa hai id nhỏ hơn bên bộ đệm, nhà sản xuất được phép viết.
(Nếu nhà sản xuấtCallId lớn hơn ConsumerCallId + bufferSize gần đây, điều đó có nghĩa là bộ đệm đã đầy và nhà sản xuất buộc phải chờ xe buýt cho đến khi có chỗ.)
Sau đó, nhà sản xuất được chỉ định vị trí trong bộ đệm dựa trên callId của anh ta (đó là prducerCallId modulo bufferSize, nhưng vì bộ đệm kích thước luôn có sức mạnh bằng 2 (giới hạn được thực thi khi tạo bộ đệm), nên thao tác Actuall được sử dụng là ProducCallId & (bufferSize - 1 )). Sau đó, nó là miễn phí để sửa đổi sự kiện trong khe đó.
(Thuật toán thực tế phức tạp hơn một chút, liên quan đến bộ nhớ cache của người tiêu dùng gần đây trong một tài liệu tham khảo nguyên tử riêng biệt, cho mục đích tối ưu hóa.)
Khi sự kiện được sửa đổi, thay đổi là "xuất bản". Khi xuất bản vị trí tương ứng trong mảng cờ được điền với cờ đã cập nhật. Giá trị cờ là số vòng lặp (managerCallId chia cho đệmSize (một lần nữa vì đệmSize là lũy thừa của 2, hoạt động thực tế là một ca đúng).
Theo cách tương tự có thể có bất kỳ số lượng người tiêu dùng. Mỗi khi người tiêu dùng muốn truy cập vào bộ đệm, một ConsumerCallId được tạo ra (tùy thuộc vào cách người tiêu dùng được thêm vào người gây rối, nguyên tử được sử dụng trong thế hệ id có thể được chia sẻ hoặc tách riêng cho từng người trong số họ). ConsumerCallId này sau đó được so sánh với producentCallId gần đây nhất và nếu nó kém hơn hai, người đọc được phép tiến bộ.
(Tương tự nếu nhà sản xuấtCallId thậm chí là với ConsumerCallId, điều đó có nghĩa là bộ đệm là hợp lý và người tiêu dùng buộc phải chờ đợi. Cách chờ đợi được xác định bởi WaitStrargety trong quá trình tạo ra kẻ gây rối.)
Đối với người tiêu dùng cá nhân (những người có trình tạo id riêng), điều tiếp theo được kiểm tra là khả năng tiêu thụ hàng loạt. Các vị trí trong bộ đệm được kiểm tra theo thứ tự từ một vị trí tương ứng với ConsumerCallId (chỉ số được xác định theo cách tương tự như đối với nhà sản xuất), đến vị trí tương ứng với nhà sản xuất gần đây của nhà sản xuất.
Chúng được kiểm tra trong một vòng lặp bằng cách so sánh giá trị cờ được viết trong mảng cờ, so với giá trị cờ được tạo cho ConsumerCallId. Nếu các cờ trùng khớp, điều đó có nghĩa là các nhà sản xuất điền vào các vị trí đã cam kết thay đổi của họ. Nếu không, vòng lặp bị hỏng và thay đổi được cam kết cao nhất được trả về. Các vị trí từ ConsumerCallId đến nhận được trong ChangeId có thể được tiêu thụ theo đợt.
Nếu một nhóm người tiêu dùng đọc cùng nhau (những người có trình tạo id dùng chung), mỗi người chỉ nhận một cuộc gọi duy nhất và chỉ có vị trí cho cuộc gọi duy nhất đó được kiểm tra và trả lại.