0
点赞
收藏
分享

微信扫一扫

【设计模式】原型模式——Netty源码中的原型模式

Netty源码中的原型模式之所以有必要单独拿出来讲,是因为Netty有独特的数据结构实现了原型模式,并且还提供了深拷贝的实现思路,所以需要做一个详细的分析。


NonBlockingHashMap

NonBlockingHashMap是Netty用来代替ConcurrentHashMap的数据结构,可以理解为线程安全的HashMap,但与HashMap不同的是,key和value都不可以为null。它和ConcurrentHashMap有一些相似点,扩容时利用多线程加速复制数据,利用数组统计size减少线程竞争。尽管它不会阻塞线程,速度更快,但比ConcurrentHashMap更耗资源,而且伸缩性不好,使用时要做一些取舍。

public class NonBlockingHashMap<TypeK, TypeV>
  extends AbstractMap<TypeK, TypeV>
  implements ConcurrentMap<TypeK, TypeV>, Cloneable, Serializable {

	/**
   * Creates a shallow copy of this hashtable. All the structure of the
   * hashtable itself is copied, but the keys and values are not cloned.
   * This is a relatively expensive operation.
   *
   * @return  a clone of the hashtable.
   */
  @Override
  public Object clone() {
    try {
      NonBlockingHashMap<TypeK,TypeV> t = (NonBlockingHashMap<TypeK,TypeV>) super.clone();
      t.clear();
      // Now copy sanely
      for( TypeK K : keySet() ) {
        final TypeV V = get(K);  // Do an official 'get'
        t.put(K,V);
      }
      return t;
    } catch (CloneNotSupportedException e) {
      // this shouldn't happen, since we are Cloneable
      throw new InternalError();
    }
  }

}

注释写的是clone()方法创建了此数据结构的浅拷贝。它本身的所有结构都会被拷贝,但key和value都不会被拷贝,而是原封不动重新输入新的实例里。因为严格意义上的深拷贝是比较耗费资源的操作。

无独有偶,Netty另一个特色数据结构NonBlockingIdentityHashMap的原型模式实现方式和NonBlockingHashMap一模一样,因此不做赘述。


AbstractBootstrap

AbstractBootstrap是Netty的一个工具类,用于服务器通道的一系列配置,譬如绑定NioEventLoopGroup线程组、指定NIO的模式、指定子处理器、处理workerGroup、指定端口等。其有ServerBootstrap、Bootstrap两个具体的子类。

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {
    // ……代码省略……

    /**
     * Returns a deep clone of this bootstrap which has the identical configuration.  This method is useful when making
     * multiple {@link Channel}s with similar settings.  Please note that this method does not clone the
     * {@link EventLoopGroup} deeply but shallowly, making the group a shared resource.
     */
    @Override
    @SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException")
    public abstract B clone();

    // ……代码省略……
}

可见AbstractBootstrap的clone()方法的意义在于提醒子类实现本身的深拷贝,并且要记得给EventLoopGroup也做一个深拷贝。

Bootstrap与原型模式有关的代码如下:

public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {

    // ……代码省略……
    
    public Bootstrap() { }

    private Bootstrap(Bootstrap bootstrap) {
        super(bootstrap);
        resolver = bootstrap.resolver;
        remoteAddress = bootstrap.remoteAddress;
    }

    @Override
    @SuppressWarnings("CloneDoesntCallSuperClone")
    public Bootstrap clone() {
        return new Bootstrap(this);
    }

    /**
     * Returns a deep clone of this bootstrap which has the identical configuration except that it uses
     * the given {@link EventLoopGroup}. This method is useful when making multiple {@link Channel}s with similar
     * settings.
     */
    public Bootstrap clone(EventLoopGroup group) {
        Bootstrap bs = new Bootstrap(this);
        bs.group = group;
        return bs;
    }
    
    // ……代码省略……
}

可见Bootstrap继承的clone()方法并没有对EventLoopGroup成员变量进行深拷贝,而是靠带一个参数的同名方法实现的深拷贝。

ServerBootstrap与原型模式有关的代码如下:

public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {

    // ……代码省略……

    public ServerBootstrap() { }

    private ServerBootstrap(ServerBootstrap bootstrap) {
        super(bootstrap);
        childGroup = bootstrap.childGroup;
        childHandler = bootstrap.childHandler;
        synchronized (bootstrap.childOptions) {
            childOptions.putAll(bootstrap.childOptions);
        }
        childAttrs.putAll(bootstrap.childAttrs);
    }

    @Override
    @SuppressWarnings("CloneDoesntCallSuperClone")
    public ServerBootstrap clone() {
        return new ServerBootstrap(this);
    }
    
    // ……代码省略……
}

可见ServerBootstrap实现了EventLoopGroup的深拷贝。


举报

相关推荐

0 条评论