diff --git a/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java b/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java index 14bb7a9820..ab35f06504 100644 --- a/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java +++ b/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java @@ -38,8 +38,9 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.Collections; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * {@link AbstractBootstrap} is a helper class that makes it easy to bootstrap a {@link Channel}. It support @@ -54,8 +55,8 @@ public abstract class AbstractBootstrap, C ext @SuppressWarnings("deprecation") private volatile ChannelFactory channelFactory; private volatile SocketAddress localAddress; - private final Map, Object> options = new LinkedHashMap, Object>(); - private final Map, Object> attrs = new LinkedHashMap, Object>(); + private final Map, Object> options = new ConcurrentHashMap, Object>(); + private final Map, Object> attrs = new ConcurrentHashMap, Object>(); private volatile ChannelHandler handler; AbstractBootstrap() { @@ -67,12 +68,8 @@ public abstract class AbstractBootstrap, C ext channelFactory = bootstrap.channelFactory; handler = bootstrap.handler; localAddress = bootstrap.localAddress; - synchronized (bootstrap.options) { - options.putAll(bootstrap.options); - } - synchronized (bootstrap.attrs) { - attrs.putAll(bootstrap.attrs); - } + options.putAll(bootstrap.options); + attrs.putAll(bootstrap.attrs); } /** @@ -166,13 +163,9 @@ public abstract class AbstractBootstrap, C ext public B option(ChannelOption option, T value) { ObjectUtil.checkNotNull(option, "option"); if (value == null) { - synchronized (options) { - options.remove(option); - } + options.remove(option); } else { - synchronized (options) { - options.put(option, value); - } + options.put(option, value); } return self(); } @@ -184,13 +177,9 @@ public abstract class AbstractBootstrap, C ext public B attr(AttributeKey key, T value) { ObjectUtil.checkNotNull(key, "key"); if (value == null) { - synchronized (attrs) { - attrs.remove(key); - } + attrs.remove(key); } else { - synchronized (attrs) { - attrs.put(key, value); - } + attrs.put(key, value); } return self(); } @@ -384,17 +373,6 @@ public abstract class AbstractBootstrap, C ext */ public abstract AbstractBootstrapConfig config(); - static Map copiedMap(Map map) { - final Map copied; - synchronized (map) { - if (map.isEmpty()) { - return Collections.emptyMap(); - } - copied = new LinkedHashMap(map); - } - return Collections.unmodifiableMap(copied); - } - final Map, Object> options0() { return options; } @@ -424,10 +402,18 @@ public abstract class AbstractBootstrap, C ext return copiedMap(attrs); } - static void setChannelOptions( - Channel channel, Map, Object> options, InternalLogger logger) { - for (Map.Entry, Object> e: options.entrySet()) { - setChannelOption(channel, e.getKey(), e.getValue(), logger); + static Map copiedMap(Map map) { + if (map.isEmpty()) { + return Collections.emptyMap(); + } + return Collections.unmodifiableMap(new HashMap(map)); + } + + static void setAttributes(Channel channel, Map.Entry, Object>[] attrs) { + for (Map.Entry, Object> e: attrs) { + @SuppressWarnings("unchecked") + AttributeKey key = (AttributeKey) e.getKey(); + channel.attr(key).set(e.getValue()); } } @@ -438,6 +424,16 @@ public abstract class AbstractBootstrap, C ext } } + @SuppressWarnings("unchecked") + static Map.Entry, Object>[] newAttrArray(int size) { + return new Map.Entry[size]; + } + + @SuppressWarnings("unchecked") + static Map.Entry, Object>[] newOptionArray(int size) { + return new Map.Entry[size]; + } + @SuppressWarnings("unchecked") private static void setChannelOption( Channel channel, ChannelOption option, Object value, InternalLogger logger) { diff --git a/transport/src/main/java/io/netty/bootstrap/Bootstrap.java b/transport/src/main/java/io/netty/bootstrap/Bootstrap.java index 758475e536..7e3f478ae8 100644 --- a/transport/src/main/java/io/netty/bootstrap/Bootstrap.java +++ b/transport/src/main/java/io/netty/bootstrap/Bootstrap.java @@ -18,7 +18,6 @@ package io.netty.bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPromise; import io.netty.channel.EventLoop; @@ -27,7 +26,6 @@ import io.netty.resolver.AddressResolver; import io.netty.resolver.DefaultAddressResolverGroup; import io.netty.resolver.NameResolver; import io.netty.resolver.AddressResolverGroup; -import io.netty.util.AttributeKey; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.FutureListener; import io.netty.util.internal.ObjectUtil; @@ -256,21 +254,12 @@ public class Bootstrap extends AbstractBootstrap { @Override @SuppressWarnings("unchecked") - void init(Channel channel) throws Exception { + void init(Channel channel) { ChannelPipeline p = channel.pipeline(); p.addLast(config.handler()); - final Map, Object> options = options0(); - synchronized (options) { - setChannelOptions(channel, options, logger); - } - - final Map, Object> attrs = attrs0(); - synchronized (attrs) { - for (Entry, Object> e: attrs.entrySet()) { - channel.attr((AttributeKey) e.getKey()).set(e.getValue()); - } - } + setChannelOptions(channel, options0().entrySet().toArray(newOptionArray(0)), logger); + setAttributes(channel, attrs0().entrySet().toArray(newAttrArray(0))); } @Override diff --git a/transport/src/main/java/io/netty/bootstrap/ServerBootstrap.java b/transport/src/main/java/io/netty/bootstrap/ServerBootstrap.java index 33d858dbe5..c0041936e2 100644 --- a/transport/src/main/java/io/netty/bootstrap/ServerBootstrap.java +++ b/transport/src/main/java/io/netty/bootstrap/ServerBootstrap.java @@ -32,9 +32,9 @@ import io.netty.util.internal.ObjectUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; -import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; /** @@ -45,8 +45,8 @@ public class ServerBootstrap extends AbstractBootstrap, Object> childOptions = new LinkedHashMap, Object>(); - private final Map, Object> childAttrs = new LinkedHashMap, Object>(); + private final Map, Object> childOptions = new ConcurrentHashMap, Object>(); + private final Map, Object> childAttrs = new ConcurrentHashMap, Object>(); private final ServerBootstrapConfig config = new ServerBootstrapConfig(this); private volatile EventLoopGroup childGroup; private volatile ChannelHandler childHandler; @@ -57,12 +57,8 @@ public class ServerBootstrap extends AbstractBootstrap ServerBootstrap childOption(ChannelOption childOption, T value) { ObjectUtil.checkNotNull(childOption, "childOption"); if (value == null) { - synchronized (childOptions) { - childOptions.remove(childOption); - } + childOptions.remove(childOption); } else { - synchronized (childOptions) { - childOptions.put(childOption, value); - } + childOptions.put(childOption, value); } return this; } @@ -130,37 +122,21 @@ public class ServerBootstrap extends AbstractBootstrap, Object> options = options0(); - synchronized (options) { - setChannelOptions(channel, options, logger); - } - - final Map, Object> attrs = attrs0(); - synchronized (attrs) { - for (Entry, Object> e: attrs.entrySet()) { - @SuppressWarnings("unchecked") - AttributeKey key = (AttributeKey) e.getKey(); - channel.attr(key).set(e.getValue()); - } - } + void init(Channel channel) { + setChannelOptions(channel, options0().entrySet().toArray(newOptionArray(0)), logger); + setAttributes(channel, attrs0().entrySet().toArray(newAttrArray(0))); ChannelPipeline p = channel.pipeline(); final EventLoopGroup currentChildGroup = childGroup; final ChannelHandler currentChildHandler = childHandler; - final Entry, Object>[] currentChildOptions; - final Entry, Object>[] currentChildAttrs; - synchronized (childOptions) { - currentChildOptions = childOptions.entrySet().toArray(newOptionArray(0)); - } - synchronized (childAttrs) { - currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0)); - } + final Entry, Object>[] currentChildOptions = + childOptions.entrySet().toArray(newOptionArray(0)); + final Entry, Object>[] currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0)); p.addLast(new ChannelInitializer() { @Override - public void initChannel(final Channel ch) throws Exception { + public void initChannel(final Channel ch) { final ChannelPipeline pipeline = ch.pipeline(); ChannelHandler handler = config.handler(); if (handler != null) { @@ -191,16 +167,6 @@ public class ServerBootstrap extends AbstractBootstrap, Object>[] newAttrArray(int size) { - return new Entry[size]; - } - - @SuppressWarnings("unchecked") - private static Map.Entry, Object>[] newOptionArray(int size) { - return new Map.Entry[size]; - } - private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter { private final EventLoopGroup childGroup; @@ -238,10 +204,7 @@ public class ServerBootstrap extends AbstractBootstrap, Object> e: childAttrs) { - child.attr((AttributeKey) e.getKey()).set(e.getValue()); - } + setAttributes(child, childAttrs); try { childGroup.register(child).addListener(new ChannelFutureListener() {