2014-02-17 47 views
1

我得到下面的代碼片斷:DatagramChannel,阻塞模式和cpu

datagramChannel = DatagramChannel 
    .open(StandardProtocolFamily.INET).setOption(StandardSocketOptions.SO_REUSEADDR, true) 
    .setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface); 
datagramChannel.configureBlocking(true); 
datagramChannel.bind(new InetSocketAddress(filter.getType() 
    .getPort(filter.getTimeFrameType()))); 
datagramChannel.join(group, networkInterface); 
datagramChannel.receive(buffer); 

此代碼位於在Callable和創建高達12 Callable秒(12個線程因而)以檢索不同的數據的多播包來自12個不同的端口。它只能從每3-8秒在網絡上廣播的信息讀取。

當連續彙集12個端口(等待信息,獲取信息,等等)時,它吃掉我的一個CPU的100%。

繪製與JVisualVM執行,我看到的執行時間90%用於java.nio.channels.DatagramChannel#receive(),更確切地說com.sun.nio.ch.DatagramChannelImpl#receiveIntoBuffer()

  1. 我不明白爲什麼阻塞模式吃這麼多的CPU。

  2. 我已經閱讀使用Selector!而非阻塞模式的一些文章,但我真的不明白爲什麼Selector一個while (true)會少消耗比阻塞通道。

+0

您不是「連續輪詢12個端口」,除非您設置的讀取超時時間非常短,您沒有向我們顯示。您正在以阻止模式一次從一個端口讀取數據。我希望你沒有做所有的套接字創建和綁定,並且每次都在循環中加入。 – EJP

+0

當我說「連續輪詢12個港口」時,我的意思是說12個港口的信息是同時播出的,而且一旦讀完,我就再去等待和閱讀。讀取超時大約在每個端口5秒鐘。事實上,我不是每次都在做整個創作和約束。 – PomCompot

回答

1

問題是您使用的是沒有選擇器的NIO。

沒有選擇器的NIO可以使用,但是然後Channel.receive會不斷地嘗試讀取哪個會顯示爲一個線程的高CPU使用率。

有2個解決方案: -

  • 使用選擇,以檢測是否有東西可以讀。僅當選擇器指示有數據要讀取時才調用channel.receive
  • 使用java.net.DatagramSocket/DatagramPacket以阻止模式發送/接收。
+0

感謝那些提示。我不再擔心這個代碼,但我會在一段代碼中測試這個代碼。 – PomCompot