Ai đó có thể giải thích một cách đơn giản các mô hình gây rối là gì?


Câu trả lời:


33

Các Fowler Điều các nhà cung cấp một mồi tốt, và lời giải thích này:

Ở mức độ thô sơ, bạn có thể nghĩ về Disruptor như một biểu đồ đa tuyến của hàng đợi nơi các nhà sản xuất đặt các đối tượng lên đó được gửi đến tất cả người tiêu dùng để tiêu thụ song song thông qua các hàng đợi xuôi dòng riêng biệt. Khi bạn nhìn vào bên trong, bạn sẽ thấy rằng mạng lưới hàng đợi này thực sự là một cấu trúc dữ liệu duy nhất - bộ đệm vòng.

Mỗi nhà sản xuất và người tiêu dùng có một bộ đếm trình tự để chỉ ra khe nào trong bộ đệm mà nó hiện đang làm việc. Mỗi nhà sản xuất / người tiêu dùng viết bộ đếm trình tự riêng của mình nhưng có thể đọc bộ đếm trình tự của người khác. Bằng cách này, nhà sản xuất có thể đọc các bộ đếm của người tiêu dùng để đảm bảo vị trí mà họ muốn ghi có sẵn mà không có bất kỳ khóa nào trên quầy. Tương tự, người tiêu dùng có thể đảm bảo nó chỉ xử lý tin nhắn sau khi người tiêu dùng khác thực hiện với nó bằng cách xem các quầy.

nhập mô tả hình ảnh ở đây

Một cách tiếp cận thông thường hơn có thể sử dụng Hàng đợi của nhà sản xuất và Hàng đợi của người tiêu dùng, mỗi cách sử dụng các khóa làm cơ chế tương tranh. Trong thực tế, điều xảy ra với hàng đợi của nhà sản xuất và người tiêu dùng là hàng đợi hoàn toàn trống hoặc hoàn toàn đầy đủ hầu hết thời gian, điều này gây ra sự tranh chấp khóa và lãng phí chu kỳ đồng hồ. Kẻ gây rối làm giảm bớt điều này, một phần, bằng cách tất cả các nhà sản xuất và người tiêu dùng sử dụng cùng một cơ chế xếp hàng, phối hợp với nhau bằng cách xem các bộ đếm trình tự thay vì sử dụng các cơ chế khóa.


9

Từ bài viết này về CoralQueue :

Mẫu ngắt là một hàng đợi được sao lưu bởi một mảng tròn (tức là bộ đệm vòng) chứa đầy các đối tượng chuyển được phân bổ trước, sử dụng các rào cản bộ nhớ để đồng bộ hóa nhà sản xuất và người tiêu dùng thông qua các chuỗi.

Vì vậy, các nhà sản xuất và người tiêu dùng không giẫm đạp lên nhau trong mảng tròn bằng cách kiểm tra trình tự tương ứng của họ . Và để truyền đạt trình tự của họ qua lại với nhau, họ sử dụng các rào cản bộ nhớ thay vì khóa. Đó là cách không khóa nhanh nhất mà họ có thể giao tiếp.

May mắn thay, bạn không cần phải đi xuống các chi tiết bên trong của mẫu kẻ gây rối để sử dụng nó. Bên cạnh việc triển khai LMAX còn có CoralQueue được phát triển bởi Coral Blocks, mà tôi đang liên kết. Một số người thấy dễ hiểu một khái niệm hơn bằng cách đọc mã, vì vậy dưới đây là một ví dụ đơn giản về một nhà sản xuất gửi tin nhắn đến một người tiêu dùng. Bạn cũng có thể kiểm tra câu hỏi này để biết ví dụ về demultiplexer (một nhà sản xuất cho nhiều người tiêu dùng).

package com.coralblocks.coralqueue.sample.queue;

import com.coralblocks.coralqueue.AtomicQueue;
import com.coralblocks.coralqueue.Queue;
import com.coralblocks.coralqueue.util.Builder;

public class Basics {

    public static void main(String[] args) {

        final Queue<StringBuilder> queue = new AtomicQueue<StringBuilder>(1024, new Builder<StringBuilder>() {
            @Override
            public StringBuilder newInstance() {
                return new StringBuilder(1024);
            }
        });

        Thread producer = new Thread(new Runnable() {

            private final StringBuilder getStringBuilder() {
                StringBuilder sb;
                while((sb = queue.nextToDispatch()) == null) {
                    // queue can be full if the size of the queue
                    // is small and/or the consumer is too slow

                    // busy spin (you can also use a wait strategy instead)
                }
                return sb;
            }

            @Override
            public void run() {

                StringBuilder sb;

                while(true) { // the main loop of the thread

                    // (...) do whatever you have to do here...

                    // and whenever you want to send a message to
                    // the other thread you can just do:
                    sb = getStringBuilder();
                    sb.setLength(0);
                    sb.append("Hello!");
                    queue.flush();

                    // you can also send in batches to increase throughput:
                    sb = getStringBuilder();
                    sb.setLength(0);
                    sb.append("Hi!");

                    sb = getStringBuilder();
                    sb.setLength(0);
                    sb.append("Hi again!");

                    queue.flush(); // dispatch the two messages above...
                }
            }
        }, "Producer");

        Thread consumer = new Thread(new Runnable() {

            @Override
            public void run() {

                while (true) { // the main loop of the thread

                    // (...) do whatever you have to do here...

                    // and whenever you want to check if the producer
                    // has sent a message you just do:

                    long avail;
                    while((avail = queue.availableToPoll()) == 0) {
                        // queue can be empty!
                        // busy spin (you can also use a wait strategy instead)
                    }

                    for(int i = 0; i < avail; i++) {
                        StringBuilder sb = queue.poll();
                        // (...) do whatever you want to do with the data
                        // just don't call toString() to create garbage...
                        // copy byte-by-byte instead...
                    }
                    queue.donePolling();
                }
            }
        }, "Consumer");

        consumer.start();
        producer.start();
    }
}

Tuyên bố miễn trừ trách nhiệm: Tôi là một trong những nhà phát triển của CoralQueue.


1
Sẽ là tốt đẹp để nêu mối liên kết của bạn với phần mềm bạn mô tả.
Deer Hunter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.