240 发简信
IP属地:香港
  • 另外,我debug了一下netty的flush流程,在addFlush之后,进行doWrite的时候,会把整个链表的所有entry中的msg全都放到ByteBuffer(java原生)里(这也是我们进行两次write再进行一次writeAndFlush或者flush时,会把之前两次write的内容一起写到socket里的原因),然后再通过原生channel写出去,这里很多细节,希望能展开讲一下~

    netty源码分析之writeAndFlush全解析

    前言 在前面的文章中,我们已经详细阐述了事件和异常传播在netty中的实现,(netty源码分析之pipeline(一),netty源码分析之pipeline(二)),其中有...

  • 这里有个问题,flush的时候,以NIO为例,doWrite会直接走到NioSocketChannel里,而不是AbstractNioByteChannel。

    netty源码分析之writeAndFlush全解析

    前言 在前面的文章中,我们已经详细阐述了事件和异常传播在netty中的实现,(netty源码分析之pipeline(一),netty源码分析之pipeline(二)),其中有...

  • @简书闪电侠 :smile:谢谢谢谢。只是一个猜测。还是作者最有发言权

    netty源码分析之pipeline(一)

    通过前面的源码系列文章中的netty reactor线程三部曲,我们已经知道,netty的reactor线程就像是一个发动机,驱动着整个netty框架的运行,而服务端的绑定和...

  • 如果headContext不实现inboundhandler接口 invokeChannelRead接口需要这么写:

    if ( handler() instanceof HeadContext) {
    (HeandContext)handler() . invokeRead
    } else {
    ((ChannelInboundHandler) handler()).channelRead(this, msg);
    }

    需要对headcontext做特殊处理。这是不优雅的,既然如此,就直接实现inboundhandler接口就好了~

    netty源码分析之pipeline(一)

    通过前面的源码系列文章中的netty reactor线程三部曲,我们已经知道,netty的reactor线程就像是一个发动机,驱动着整个netty框架的运行,而服务端的绑定和...

  • 或者说强转出错了。。。 括号中写重复了

    netty源码分析之pipeline(一)

    通过前面的源码系列文章中的netty reactor线程三部曲,我们已经知道,netty的reactor线程就像是一个发动机,驱动着整个netty框架的运行,而服务端的绑定和...

  • @简书闪电侠
    唔。我看了一下代码。我觉得HeadContext实现inBound和outBound接口,实际是本身却只是一个outBoundContext。这个原因要从fireChannelRead说起

    AbstractChannelHandlerContext#invokeChannelRead方法,会执行一个Handler的channelRead(在HeadContext里这个handler就是HeadContext自己),这个channelRead方法是inBoundHandler的方法。

    作为读的起始点,如果headContext不实现inBoundHandler,那么传递的时候,就不优雅了。

    因为执行pipeline.fireChannelRead(byteBuf) -> AbstractChannelHandlerContext.invokeChannelRead(head, msg); -> ((ChannelInboundHandler) handler()).channelRead(this, msg) 这里最后一步,就走不通了(或者说不通用了)。

    我反过来说,HeadContext不实现inboundhandler会怎样。

    private void invokeChannelRead(Object msg) {
    if (invokeHandler()) {
    try {
    ((ChannelInboundHandler) handler()).channelRead(this, msg);
    } catch (Throwable t) {
    notifyHandlerException(t);
    }
    } else {
    fireChannelRead(msg);
    }
    }
    这个方法中,(ChannelInboundHandler) handler()这一步就会直接报错,这里的实现就会比较不优雅。

    总的来说,我认为,其实netty把head实现了inbound和outbound handler,但是却只认为head是一个outbound的context,主要是为了:
    1.能在执行`invokeChannelRead`的时候,不用对headContext特殊处理
    2.outBound就不用多说了,就是为了能让数据流出的时候流经head节点。

    netty源码分析之pipeline(一)

    通过前面的源码系列文章中的netty reactor线程三部曲,我们已经知道,netty的reactor线程就像是一个发动机,驱动着整个netty框架的运行,而服务端的绑定和...

  • 为什么HeadContext实现了ChannelInboundHandler
    但是在初始化时,却把自己设置为 inbound = false?

    netty源码分析之pipeline(一)

    通过前面的源码系列文章中的netty reactor线程三部曲,我们已经知道,netty的reactor线程就像是一个发动机,驱动着整个netty框架的运行,而服务端的绑定和...

  • 可能是一种权衡,线程池保证提交的任务要优先执行。而且应该不存在空闲的线程,空闲的线程都在while循环里不停地从workQueue中取任务呢。。

    深入分析java线程池的实现原理

    简书 占小狼[//www.greatytc.com/users/90ab66c248e6/latest_articles] 转载请注明原创出处,谢谢! 2019/...

  • 最小值可能为0、1或者corePoolSize

    深入分析java线程池的实现原理

    简书 占小狼[//www.greatytc.com/users/90ab66c248e6/latest_articles] 转载请注明原创出处,谢谢! 2019/...

  • 补充一些东西。关于一个Worker如果从队列中取不到task的情况(已经没有任务可以执行了)。
    这个时候会执行一个processWorkerExit的方法,这个方法先看worker退出的原因是不是由于用户提交的任务中有异常,如果是,把worker的数量减一。
    再从工作队列中移除worker。
    然后看看线程池是否是运行的。如果是运行的并且worker退出的原因是由于用户任务中的异常,则新增一个worker(官方文档上说是“替换”这个worker)。
    如果不是,则根据allowCoreThreadTimeOut字段取和workQueue是否为空取一个最小值,最小值可能为0或者corePoolSize。如果工作的worker数量小于这个最小值,则同样新增一个worker

    深入分析java线程池的实现原理

    简书 占小狼[//www.greatytc.com/users/90ab66c248e6/latest_articles] 转载请注明原创出处,谢谢! 2019/...

  • jdk1.8并没有出现“对象优先在Eden分配”中示例的结果。
    public class TestGC {
    private static final int _1MB = 1024 * 1024;

    private volatile static byte[] allocation1, allocation2, allocation3, allocation4;

    /**
    * VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails
    * -XX:SurvivorRatio=8
    */
    public static void testAllocation() {
    allocation1 = new byte[2 * _1MB];
    allocation2 = new byte[2 * _1MB];
    allocation3 = new byte[2 * _1MB];
    allocation4 = new byte[4 * _1MB]; // 出现一次Minor GC
    }

    public static void main(String[] args) throws IOException {
    testAllocation();
    System.in.read();
    }
    }

    上述代码的运行结果:
    Heap
    PSYoungGen total 9216K, used 7308K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
    eden space 8192K, 89% used [0x00000007bf600000,0x00000007bfd23218,0x00000007bfe00000)
    from space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)
    to space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
    ParOldGen total 10240K, used 4096K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
    object space 10240K, 40% used [0x00000007bec00000,0x00000007bf000010,0x00000007bf600000)
    Metaspace used 2737K, capacity 4486K, committed 4864K, reserved 1056768K
    class space used 298K, capacity 386K, committed 512K, reserved 1048576K

    我们可以看到两个结果:
    1.并没有发生gc,这是个好事
    2.年轻代使用了89%,这里面应该有6mb是allocation1、2、3,而allocation4直接分配在了老年代(日志中显示:老年代使用了40%)

    看来新版的虚拟机把这个地方优化了,上述情况不会进行一次YGC了

    深入理解JVM(6) : Java对象内存分配策略

    Java技术体系中所提倡的自动内存管理最终可以归结为自动化地解决了两个问题:给对象分配内存以及回收分配给对象的内存。 对象的内存回收,可参考 java内存回收1 和 jav...

  • @如入心随 像我学习就别了,哈哈哈,我就是个半吊子,一起努力!

    我不以学校为骄傲,心怀感激就好

    毕业生晚会之后马上就是答辩,然后就是离校,大学四年,走人连四天都不用。 今晚毕业生晚会,我本来以为我应该没啥感触,我有啥感触呢!四年中一年半不在学校,半年不怎么上课,但是真到...

  • @如入心随 电子商务。

    我不以学校为骄傲,心怀感激就好

    毕业生晚会之后马上就是答辩,然后就是离校,大学四年,走人连四天都不用。 今晚毕业生晚会,我本来以为我应该没啥感触,我有啥感触呢!四年中一年半不在学校,半年不怎么上课,但是真到...