2013-01-31 61 views
5

誰能告訴我什麼是Disruptor設計模式與簡單的例子?我會想知道這種設計模式的基礎知識。什麼是LMAX干擾器設計模式?

+2

爲什麼你需要'設計模式'?干擾器只是一個環形緩衝區隊列,有些應用程序「準則」如何避免爭用和緩存行反彈。他們使用繁忙等待來減少延遲,所有數據通常以序列化形式存儲到環形緩衝區的預先分配的內存中,因此不會發生清理。 – bestsss

+0

我需要這個用於我的股票市場網絡應用程序(www.askkuber.com),我們有很多線程支持的處理。 –

+0

除非你需要實時更新時間(這意味着沒有網絡),你可以依靠簡單的執行器或Fork/Join。即使這樣也沒關係。 – bestsss

回答

4

一個簡單的谷歌給了我大量的信息,包括this introduction由Martin Fowler

在粗級別,你可以把干擾器爲一體的 隊列,生產者將物體放在它的多播圖被髮送通過單獨的下游隊列向所有的消費者進行並行消費。 當你在裏面看時,你會發現這個隊列網絡真的是一個單一的數據結構 - 一個環形緩衝區。每個生產者和消費者都有一個序列計數器,用於指示當前在哪個緩衝區中的 。每個生產者/消費者編寫自己的序列計數器,但 可以讀取其他序列計數器。通過這種方式,製片人可以讀取 消費者計數器,以確保其想要寫入的插槽是 ,而且在計數器上沒有任何鎖定。類似地,消費者可以通過觀察計數器來確保它只處理消息一旦其他消費者完成 。

GitHub project包含Java代碼+ doc。

+0

他們提的非常高的水平使用這種設計模式,我會想這個基本的設計模式與Java編程語言中的一些基本的例子 –

+0

你再次發佈同樣的高級別定義 –

+0

干擾器=優化叉加盟模式 – sloven

2

this article一個簡單的代碼示例:

干擾模式是一個批處理隊列,由一個圓形的 陣列(即環形緩衝區)填滿預先分配的傳輸 使用內存屏障的對象通過序列同步生產者和 消費者。

幸運的是,您並不需要了解破壞者模式的內在細節才能使用它。如果您發現通過代碼更容易理解,以下是的Hello World,這是一個用於實現干擾模式的線程間通信的超低延遲隊列。

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