使用Netty编程时,我们经常会从用户线程,而不是Netty线程池发起write操作,因为我们不能在netty的事件回调中做大量耗时操作。那么问题来了 –

1, writeAndFlush是线程安全的吗?

2, 是否使用了锁,导致并发性能下降呢

我们来看代码 – 在DefaultChannelHandlerContext中

@Override
public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
DefaultChannelHandlerContext next;
next = findContextOutbound(MASK_WRITE);
ReferenceCountUtil.touch(msg, next);
next.invoker.invokeWrite(next, msg, promise);
next = findContextOutbound(MASK_FLUSH);
next.invoker.invokeFlush(next);
return promise;
}

在DefaultChannelHandlerInvoker.java中

@Override
public void invokeWrite(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
if (msg == null) {
throw new NullPointerException("msg");
}
if (!validatePromise(ctx, promise, true)) {
// promise cancelled
ReferenceCountUtil.release(msg);
return;
} if (executor.inEventLoop()) {
invokeWriteNow(ctx, msg, promise);
} else {
AbstractChannel channel = (AbstractChannel) ctx.channel();
int size = channel.estimatorHandle().size(msg);
if (size > 0) {
ChannelOutboundBuffer buffer = channel.unsafe().outboundBuffer();
// Check for null as it may be set to null if the channel is closed already
if (buffer != null) {
buffer.incrementPendingOutboundBytes(size);
}
}
safeExecuteOutbound(WriteTask.newInstance(ctx, msg, size, promise), promise, msg);
}
}
private void safeExecuteOutbound(Runnable task, ChannelPromise promise, Object msg) {
try {
executor.execute(task);
} catch (Throwable cause) {
try {
promise.setFailure(cause);
} finally {
ReferenceCountUtil.release(msg);
}
}
}

可见,writeAndFlush如果在Netty线程池内执行,则是直接write;否则,将作为一个task插入到Netty线程池执行。

《Netty权威指南》写到
通过调用NioEventLoop的execute(Runnable task)方法实现,Netty有很多系统Task,创建他们的主要原因是:当I/O线程和用户线程同时操作网络资源时,为了防止并发操作导致的锁竞争,将用户线程的操作封装成Task放入消息队列中,由I/O线程负责执行,这样就实现了局部无锁化。

参考
http://www.cnblogs.com/zemliu/p/3667332.html
http://netty.io/5.0/xref/io/netty/channel/DefaultChannelHandlerInvoker.html
http://www.infoq.com/cn/articles/netty-version-upgrade-history-thread-part/

最新文章

  1. Redis使用总结之与Memcached异同
  2. [Angular2 Form] Understand the Angular 2 States of Inputs: Pristine and Untouched
  3. 二、记一次失败的 CAS 搭建 之 证书配置
  4. Android中Bitmap和Drawable,等相关内容
  5. JAVA NIO之Character Set
  6. hdu 3062 2-sat入门题
  7. SQL Server 2005无日志文件附加数据库
  8. 情景linux--如何优雅地退出telnet
  9. sass创建web项目环境步骤
  10. C# CRC - 16
  11. JVM笔记(虚拟机各内存的介绍)
  12. JAVA课程课后作业03之动手动脑
  13. 009-ThreadPoolExecutor运转机制详解,线程池使用1-newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor、newScheduledThreadPool
  14. Spark记录-spark-submit学习
  15. IIS不能下载.apk文件
  16. redis 任务队列
  17. 初识IntPtr
  18. java基础77 Http协议及Servlet中的GET、POST提交方式
  19. js加密解密 base64
  20. Intellij IDEA 2018.2.2 SpringBoot热启动 (Maven)

热门文章

  1. Linux从零单排(二):setuptools、pip、anaconda2的环境配置
  2. java 基础一
  3. SQL学习整理_1
  4. CSS之viewport 2
  5. CSS元素居中的常用方法
  6. 安装Apache报80端口被占用 pid 4
  7. 【杂记】Asp.Net 篇
  8. 解决Windows下网络原因Composer安装失败问题
  9. Web自动化测试工具调研
  10. composer [ReflectionException] Class Fxp\Composer\AssetPlugin\Repository\NpmRepository does not exist