ChannelOption
主要是配置一些底层网络层比如说TCP协议 里面的一些设置项,而且是以线程安全的方式配置channelConfig。ChannelOption并不维护对应的vlaue,而是存储对应的类型,而具体的值是有channelConfig来设置存储的,我们来通过源码梳理ChannelOption与他的父类的继承关系 如下: ChannelOption 继承 AbstractConstant 又实现 Constant 接口 Constant又是由ConstantPool 来创建的,其中泛型《T》 是一些设置项的数据类型 比如Integer long 等,这个后续源码会做介绍。
/** * A {@link ChannelOption}聽allows to configure a {@link ChannelConfig} in a type-safe * way. Which {@link ChannelOption} is supported depends on the actual implementation * of {@link ChannelConfig} and may depend on the nature of the transport it belongs * to. * * @param <T> the type of the value which is valid for the {@link ChannelOption} */ public class ChannelOption<T> extends AbstractConstant<ChannelOption<T>>
package io.netty.util; import java.util.concurrent.atomic.AtomicLong; /** * Base implementation of {@link Constant}. */ public abstract class AbstractConstant<T extends AbstractConstant<T>> implements Constant<T> { private static final AtomicLong uniqueIdGenerator = new AtomicLong(); private final int id; private final String name; private final long uniquifier; /** * Creates a new instance. */ protected AbstractConstant(int id, String name) { this.id = id; this.name = name; this.uniquifier = uniqueIdGenerator.getAndIncrement(); }
那么Constant 接口是什么呢 ?是根据 ConstantPool 常量池来创建的,并且是一个单例的 通过一个等号运算符来比较。
那么我们来看看 ConstantPoolpackage io.netty.util; /** * A singleton which is safe to compare via the {@code ==} operator. Created and managed by {@link ConstantPool}. */ public interface Constant<T extends Constant<T>> extends Comparable<T> { /** * Returns the unique number assigned to this {@link Constant}. */ int id(); /** * Returns the name of this {@link Constant}. */ String name(); }
其中 ConcurrentMap<String, T> constants 成员变量 存放着 系统常量的类型,来看getOrCreate 方法 创建并返回类型,并且是线程安全,我们来看如何保证线程安全的 putIfAbsent 这个方法 他是 util.Concurrent.ConcurrentMap包里的方法,这个方法主要是通过 key 如果存在就返回值,如果不存在就返回null,比如两个线程 同时进入getOrCreate 方法里 并且 第一个线程 进行到final T tempConstant = newConstant(nextId(), name); 而第二个线程 已经执行完 constant = constants.putIfAbsent(name, tempConstant); 这步,也就是说 由于此时根据name 这个key 还并没有值 返回为Null, 此时 继续 if (constant == null) { return tempConstant; } 我们直接返回 刚才第二个线程 NEW出的 final T tempConstant = newConstant(nextId(), name); 这个值,再看第一个线程 执行 到 constant = constants.putIfAbsent(name, tempConstant); 返回的是第二个线程 刚存进去的值,这样通过 两个 if (constant == null) 与ConcurrentMap 就能保证 此方法的线程安全,我们来看
public abstract class ConstantPool<T extends Constant<T>> { private final ConcurrentMap<String, T> constants = PlatformDependent.newConcurrentHashMap(); private final AtomicInteger nextId = new AtomicInteger(1); /** * Shortcut of {@link #valueOf(String) valueOf(firstNameComponent.getName() + "#" + secondNameComponent)}. */ public T valueOf(Class<?> firstNameComponent, String secondNameComponent) { if (firstNameComponent == null) { throw new NullPointerException("firstNameComponent"); } if (secondNameComponent == null) { throw new NullPointerException("secondNameComponent"); } return valueOf(firstNameComponent.getName() + '#' + secondNameComponent); } /** * Returns the {@link Constant} which is assigned to the specified {@code name}. * If there's no such {@link Constant}, a new one will be created and returned. * Once created, the subsequent calls with the same {@code name} will always return the previously created one * (i.e. singleton.) * * @param name the name of the {@link Constant} */ public T valueOf(String name) { checkNotNullAndNotEmpty(name); return getOrCreate(name); } /** * Get existing constant by name or creates new one if not exists. Threadsafe * * @param name the name of the {@link Constant} */ private T getOrCreate(String name) { T constant = constants.get(name); if (constant == null) { final T tempConstant = newConstant(nextId(), name); constant = constants.putIfAbsent(name, tempConstant); if (constant == null) { return tempConstant; } } return constant; } /** * Returns {@code true} if a {@link AttributeKey} exists for the given {@code name}. */ public boolean exists(String name) { checkNotNullAndNotEmpty(name); return constants.containsKey(name); } /** * Creates a new {@link Constant} for the given {@code name} or fail with an * {@link IllegalArgumentException} if a {@link Constant} for the given {@code name} exists. */ public T newInstance(String name) { checkNotNullAndNotEmpty(name); return createOrThrow(name); } /** * Creates constant by name or throws exception. Threadsafe * * @param name the name of the {@link Constant} */ private T createOrThrow(String name) { T constant = constants.get(name); if (constant == null) { final T tempConstant = newConstant(nextId(), name); constant = constants.putIfAbsent(name, tempConstant); if (constant == null) { return tempConstant; } } throw new IllegalArgumentException(String.format("'%s' is already in use", name)); } private static String checkNotNullAndNotEmpty(String name) { ObjectUtil.checkNotNull(name, "name"); if (name.isEmpty()) { throw new IllegalArgumentException("empty name"); } return name; } protected abstract T newConstant(int id, String name); @Deprecated public final int nextId() { return nextId.getAndIncrement(); } }
我们来看DefaultChannelConfig 存储了 通道配置的默认属性值
public class DefaultChannelConfig implements ChannelConfig { public <T> boolean setOption(ChannelOption<T> option, T value) { validate(option, value); if (option == CONNECT_TIMEOUT_MILLIS) { setConnectTimeoutMillis((Integer) value); } else if (option == MAX_MESSAGES_PER_READ) { setMaxMessagesPerRead((Integer) value); } else if (option == WRITE_SPIN_COUNT) { setWriteSpinCount((Integer) value); } else if (option == ALLOCATOR) { setAllocator((ByteBufAllocator) value); } else if (option == RCVBUF_ALLOCATOR) { setRecvByteBufAllocator((RecvByteBufAllocator) value); } else if (option == AUTO_READ) { setAutoRead((Boolean) value); } else if (option == AUTO_CLOSE) { setAutoClose((Boolean) value); } else if (option == WRITE_BUFFER_HIGH_WATER_MARK) { setWriteBufferHighWaterMark((Integer) value); } else if (option == WRITE_BUFFER_LOW_WATER_MARK) { setWriteBufferLowWaterMark((Integer) value); } else if (option == WRITE_BUFFER_WATER_MARK) { setWriteBufferWaterMark((WriteBufferWaterMark) value); } else if (option == MESSAGE_SIZE_ESTIMATOR) { setMessageSizeEstimator((MessageSizeEstimator) value); } else if (option == SINGLE_EVENTEXECUTOR_PER_GROUP) { setPinEventExecutorPerGroup((Boolean) value); } else { return false; } return true; }
Attribute
作用主要是 存储业务数据对象,比如 在第一个handler 中使用,也想在第二个Handler中使用时 就可以使用Attribute,可以在程序运行当中动态的添加 你的业务数据对象。其他的与ChannelOption类似 就不多做描述了。