Netty 常量池实现以及ChannelOption与Attribute作用分析

来源:互联网 发布:无人驾驶数据标注 编辑:程序博客网 时间:2024/06/05 19:50

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 常量池来创建的,并且是一个单例的 通过一个等号运算符来比较。

package 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();}
那么我们来看看 ConstantPool 
其中 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类似 就不多做描述了。





原创粉丝点击