云自無(wú)心水自閑

          天平山上白云泉,云自無(wú)心水自閑。何必奔沖山下去,更添波浪向人間!
          posts - 288, comments - 524, trackbacks - 0, articles - 6
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          日歷

          <2014年11月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          30123456

          隨筆檔案

          積分與排名

          • 積分 - 1126048
          • 排名 - 27

          最新評(píng)論

          Netty

          Posted on 2014-11-27 07:36 云自無(wú)心水自閑 閱讀(9864) 評(píng)論(0)  編輯  收藏 所屬分類: Java心得體會(huì)
           Netty作為一個(gè)異步非阻塞式的框架,是不允許在ChannelHandler中長(zhǎng)時(shí)間處理事務(wù)(比如數(shù)據(jù)庫(kù)的操作),阻塞I/O的讀寫處理的。

          在Netty in Action中是這樣描述的:
          While the I/O thread must not be blocked at all, thus prohibiting any direct blocking operations within your ChannelHandler, there is a way to implement this requirement. 
          You can specify an EventExecutorGroup when adding ChannelHandlers to the ChannelPipeline. 
          This EventExecutorGroup will then be used to obtain an EventExecutor, which will execute all the methods of the ChannelHandler. 
          This EventExecutor will use a different thread from the I/O thread, thus freeing up the EventLoop.
          I/O線程是不允許被阻塞的,也就是不能在ChannelHandler中進(jìn)行任何阻塞式的處理,但是對(duì)此我們也有相應(yīng)的解決方法.
          就是在把ChannelHanders添加到ChannelPipeline的時(shí)候,指定一個(gè)EventExecutorGroup,ChannelHandler中所有的方法都將會(huì)在這個(gè)指定的EventExecutorGroup中運(yùn)行。
          而這個(gè)EVentExecutorGroup運(yùn)行的線程與I/O線程不同,達(dá)到不阻塞I/O的目的。 
          程序示例如下:
          Channel ch = ...;
          ChannelPipeline p = ch.pipeline();
          EventExecutor e1 = new DefaultEventExecutorGroup(16);
          EventExecutor e2 = new DefaultEventExecutorGroup(8);
           
          p.addLast(new MyProtocolCodec());
          p.addLast(e1, new MyDatabaseAccessingHandler());
          p.addLast(e2, new MyHardDiskAccessingHandler());
          需要補(bǔ)充說(shuō)明一下,上面的示例程序似乎有點(diǎn)問(wèn)題。使用上述方法添加ChannelHandler到pipeline中以后,channelHandler的所有方法確實(shí)什么在一個(gè)單獨(dú)的線程中被處理。
          但是,每次DefaultEventExcutorGroup線程池中的線程不能被重用,每次都會(huì)生成一個(gè)新的線程,然后在新的線程中調(diào)用ChannelHandler, 在visualvm可以看到線程數(shù)量直線增長(zhǎng)。

          解決的方法是:不能使用局部變量形式的DefaultEventExecutorGroup。而使用類靜態(tài)成員變量:
          static final EventExecutor e1 = new DefaultEventExecutorGroup(16);

          我分析原因可能是:在新的連接到來(lái),創(chuàng)建ChannelPipeline給新Channel的時(shí)候,如果不使用靜態(tài)的共享變量,而使用局部變量的話,就造成DefaultEventExecutorGroup被多次重復(fù)創(chuàng)建。因此,雖然一個(gè)DefaultEventExecutorGroup中的Thread數(shù)量是固定的,但是卻產(chǎn)生了多余的DefaultEventExecutorGroup。從VisualVM中也可以看到,DefaultEventExecutorGroup線程的名字會(huì)是:
          xxx-2-1
          xxx-3-1
          xxx-4-1
          xxx-n-1
          說(shuō)明是Group的數(shù)量(第一個(gè)數(shù)字)在增多,而不是Group中的線程數(shù)量(第二個(gè)數(shù)字)在增多
          改成靜態(tài)變量后,線程名會(huì)是:
          xxx-2-1
          xxx-2-2
          xxx-2-3
          xxx-2-n
          最后一個(gè)n就是在創(chuàng)建DefaultEventExecutorGroup時(shí)候,傳入的線程個(gè)數(shù)參數(shù)的大小。


          主站蜘蛛池模板: 冕宁县| 台江县| 新巴尔虎右旗| 澄迈县| 铜川市| 江陵县| 尤溪县| 南康市| 陈巴尔虎旗| 泰来县| 澎湖县| 南乐县| 民权县| 汝州市| 航空| 资溪县| 博湖县| 吉安市| 双桥区| 承德县| 望奎县| 芜湖市| 福建省| 昆山市| 漯河市| 屏南县| 义乌市| 闻喜县| 河津市| 崇文区| 乌鲁木齐市| 麟游县| 北流市| 濉溪县| 赞皇县| 安乡县| 三江| 孝感市| 兴义市| 惠安县| 罗江县|