2011-09-26 82 views
10

我剛剛發現只有一個NIO工具,即Java NIO Pipe,用於在線程之間傳遞數據。使用這種機制比通過隊列傳遞更傳統的消息(如ArrayBlockingQueue)有什麼優勢嗎?Java NIO Pipe vs BlockingQueue

+0

管道經過的內核,因爲選擇具有喚醒很少有用...這是通過在Linux上實現管... – bestsss

+0

@bestsss護理闡述?您可以通過選擇器註冊管道來接收通知,這有什麼問題? – raffian

+0

@raffian,簡單地說 - 你不能真正使用IPC來管理IPC,並且在這個過程中有很多更有效的方式來傳遞信息。 – bestsss

回答

6

通常,將數據傳遞給另一個線程進行處理的最簡單方法是使用ExecutorService。這種包裝了兩個隊列和線程池(可以有一個線程)

您可以使用一個管道時,你有支持NIO通道庫。如果你想在線程之間傳遞數據的ByteBuffers,這也很有用。

否則其通常使用ArrayBlockingQueue更簡單/更快。

如果你想要一個更快的方式在線程之間交換數據,我建議你看看Exchanger,但它不像ArrayBlockingQueue那樣具有通用性。

The Exchanger and GC-less Java

+0

謝謝,我從來沒有考慮過使用交換器使GC開銷最小化的事實。然而,換熱器的缺點是它是同步的。通常你只是想將數據抽入另一個線程而不必等待它被拾取。 – Maxaon3000

+0

管道是固定的大小。如果製片人製作速度不得不停下來,問題是一樣的。如果生產者從未在消費者完成之前填充緩衝區,則不必停止(無論是哪種情況) –

+1

管道用於實施Selector.wakeup,除此之外它們並不是非常有用,因爲僅限於內存的解決方案更有效,不要通過內核。 – bestsss

1

我想管將有更好的延遲,因爲它可以很可能與幕後協同程序來實現。因此,當數據可用時,生產者立即向消費者屈服,而不是在線程調度器決定時。

管道通常佔一個消費者 - 生產者的問題,很可能使兩個線程合作來實現這種方式,而不是外部搶佔。

2

我相信NIO管的設計,讓您可以將數據發送到在一個線程安全的方式選擇內循環的通道,換句話說,任何線程可以寫信給管和數據將在其他處理管道的極端,在選擇器迴路內部。當你寫入管道時,你可以使另一側的通道可讀。

+0

我想知道在簡單隊列輪詢上使用選擇器循環的線程之間傳遞數據的性能特徵。另外,通過管道傳遞數據似乎帶來了不必將字節而不是對象傳遞給其他線程的不便。換句話說,它迫使你爲線程間數據交換開發一個有線協議。 – Maxaon3000

+0

你的意思是在ConcurrentLinkedQueue上,對吧?這是一個很好的問題。我在ConcurrentLinkedQueue上下了我的籌碼。 :)但是我看到管道的一個優點是:你發送一條消息,就像其他人正在做的一樣,換句話說,你從一個通道讀取消息,而不是從隊列中讀取一個對象。 – chrisapotek

3

所以有很多的麻煩管(check here)之後,我決定贊成非阻塞併發隊列超過NIO管道。所以我在Java的ConcurrentLinkedQueue上做了一些基準測試。請看下圖:

public static void main(String[] args) throws Exception { 

    ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>(); 

    // first test nothing: 

    for (int j = 0; j < 20; j++) { 

     Benchmarker bench = new Benchmarker(); 

     String s = "asd"; 

     for (int i = 0; i < 1000000; i++) { 
      bench.mark(); 
      // s = queue.poll(); 
      bench.measure(); 
     } 

     System.out.println(bench.results()); 

     Thread.sleep(100); 
    } 

    System.out.println(); 

    // first test empty queue: 

    for (int j = 0; j < 20; j++) { 

     Benchmarker bench = new Benchmarker(); 

     String s = "asd"; 

     for (int i = 0; i < 1000000; i++) { 
      bench.mark(); 
      s = queue.poll(); 
      bench.measure(); 
     } 

     System.out.println(bench.results()); 

     Thread.sleep(100); 
    } 

    System.out.println(); 

    // now test polling one element on a queue with size one 

    for (int j = 0; j < 20; j++) { 

     Benchmarker bench = new Benchmarker(); 

     String s = "asd"; 
     String x = "pela"; 

     for (int i = 0; i < 1000000; i++) { 
      queue.offer(x); 
      bench.mark(); 
      s = queue.poll(); 
      bench.measure(); 
      if (s != x) throw new Exception("bad!"); 
     } 

     System.out.println(bench.results()); 

     Thread.sleep(100); 
    } 

    System.out.println(); 

    // now test polling one element on a queue with size two 

    for (int j = 0; j < 20; j++) { 

     Benchmarker bench = new Benchmarker(); 

     String s = "asd"; 
     String x = "pela"; 

     for (int i = 0; i < 1000000; i++) { 
      queue.offer(x); 
      queue.offer(x); 
      bench.mark(); 
      s = queue.poll(); 
      bench.measure(); 
      if (s != x) throw new Exception("bad!"); 
      queue.poll(); 
     } 

     System.out.println(bench.results()); 

     Thread.sleep(100); 
    } 
} 

結果:

totalLogs=1000000, minTime=0, maxTime=85000, avgTime=58.61 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=5281000, avgTime=63.35 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=725000, avgTime=59.71 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=25000, avgTime=58.13 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=378000, avgTime=58.45 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=15000, avgTime=57.71 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=170000, avgTime=58.11 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=1495000, avgTime=59.87 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=232000, avgTime=63.0 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=184000, avgTime=57.89 (times in nanos) 

totalLogs=1000000, minTime=0, maxTime=2600000, avgTime=65.22 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=850000, avgTime=60.5 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=150000, avgTime=63.83 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=43000, avgTime=59.75 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=276000, avgTime=60.02 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=457000, avgTime=61.69 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=204000, avgTime=60.44 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=154000, avgTime=63.67 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=355000, avgTime=60.75 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=338000, avgTime=60.44 (times in nanos) 

totalLogs=1000000, minTime=0, maxTime=345000, avgTime=110.93 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=396000, avgTime=100.32 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=298000, avgTime=98.93 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=1891000, avgTime=101.9 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=254000, avgTime=103.06 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=1894000, avgTime=100.97 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=230000, avgTime=99.21 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=348000, avgTime=99.63 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=922000, avgTime=99.53 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=168000, avgTime=99.12 (times in nanos) 

totalLogs=1000000, minTime=0, maxTime=686000, avgTime=107.41 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=320000, avgTime=95.58 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=248000, avgTime=94.94 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=217000, avgTime=95.01 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=159000, avgTime=93.62 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=155000, avgTime=95.28 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=106000, avgTime=98.57 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=370000, avgTime=95.01 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=1836000, avgTime=96.21 (times in nanos) 
totalLogs=1000000, minTime=0, maxTime=212000, avgTime=98.62 (times in nanos) 

結論:

的MAXTIME很可怕,但我認爲它是安全的結論,我們是在50毫微秒範圍輪詢併發隊列。