Birisi basit terimlerle yıkıcı modelin ne olduğunu açıklayabilir mi?


Yanıtlar:


33

Fowler Madde sağlayıcıları iyi astar ve bu açıklama:

Ham bir düzeyde, bir Yıkıcıyı, üreticilerin ayrı tüketiciler sıraları üzerinden paralel tüketim için tüm tüketicilere gönderilen nesneler koydukları çok noktaya yayın kuyrukları grafiği olarak düşünebilirsiniz. İçine baktığınızda, bu kuyruk ağının gerçekten tek bir veri yapısı olduğunu görüyorsunuz - bir halka tamponu.

Her üretici ve tüketici, tamponda şu anda üzerinde çalıştığı yeri gösteren bir sıra sayacına sahiptir. Her üretici / tüketici kendi dizi sayacını yazar ancak diğerlerinin dizi sayaçlarını okuyabilir. Bu şekilde üretici, yazmak istediği yuvanın sayaçlara kilitlenmeden ulaşabilmesini sağlamak için tüketicilerin sayaçlarını okuyabilir. Benzer şekilde, bir tüketici, sayaçları izleyerek başka bir tüketici yapıldığında yalnızca mesajları işlemesini sağlayabilir.

görüntü tanımını buraya girin

Daha geleneksel bir yaklaşım, her biri eşzamanlılık mekanizması olarak kilit kullanan bir Üretici Kuyruğu ve Tüketici Kuyruğu kullanabilir. Uygulamada, üretici ve tüketici sıraları ile olan şey, sıraların çoğu zaman tamamen boş ya da tamamen doludur; bu da kilitlenme çekişmesine ve boşa harcanan saat döngülerine neden olur. Yıkıcı, kısmen, tüm üreticilerin ve tüketicilerin aynı sıra mekanizmasını kullanmasını sağlayarak, kilitleme mekanizmaları kullanmak yerine sıra sayaçlarını izleyerek birbirleriyle koordine ederek bunu hafifletir.


9

CoralQueue ile ilgili bu makaleden :

Yıkıcı patern, üreticileri ve tüketicileri diziler arasında senkronize etmek için hafıza bariyerlerini kullanan önceden tahsis edilmiş transfer nesneleriyle doldurulmuş dairesel bir dizi (yani halka tamponu) ile desteklenen bir sıradır.

Dolayısıyla üreticiler ve tüketiciler , ilgili dizilerini kontrol ederek dairesel dizinin içinde birbirlerine basmazlar . Ve sekanslarını birbirlerine ileri geri iletmek için kilitler yerine hafıza bariyerlerini kullanırlar. Bu, iletişim kurabilecekleri en hızlı kilitsiz yoldur.

Neyse ki, kullanmak için bozucu paternin iç detaylarına inmenize gerek yok. LMAX uygulamasının yanı sıra, bağlı olduğum Coral Blocks tarafından geliştirilen CoralQueue var . Bazı insanlar kod okuyarak bir kavramı anlamayı daha kolay buluyorlar; bu nedenle aşağıda tek bir üreticiye tek bir tüketiciye mesaj gönderen basit bir örnek verilebilir. Bu soruyu bir çoklayıcı çözümleyici (bir çok tüketiciye bir üretici) örneği için de kontrol edebilirsiniz .

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();
    }
}

Feragatname: Ben CoralQueue'un geliştiricilerinden biriyim.


1
Açıkladığınız yazılımla olan ilişkinizi belirtmeniz iyi olur.
Deer Hunter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.