一. 耗時任務
static final EventExecutorGroup group = new DefaultEventExecutorGroup(16);
// Tell the pipeline to run MyBusinessLogicHandler's event handler methods // in a different thread than an I/O thread so that the I/O thread is not blocked by // a time-consuming task. // If your business logic is fully asynchronous or finished very quickly, you don't // need to specify a group. pipeline.addLast(group, "handler", new MyBusinessLogicHandler());
其中EventExecutorGroup 就是專門來處理耗時業務的線程池。
childHandler(new ChannelInitializer<SocketChannel>() {
static final EventExecutorGroup group = new DefaultEventExecutorGroup(16);
@Override
protected void initChannel(SocketChannel ch)
throws Exception {
ChannelPipeline p = ch.pipeline();pipeline.addLast(group, "handler", new MyBusinessLogicHandler());
此方法所在類 每次都是new ,所以會創建很多group, 所以把group 定義為static
二.執行計划
在實際生產環境中,我們可能會碰到 需要臨時執行也行計划任務,,這些任務如果不耗時,我們可以通過channel提供的計划任務方法處理:
future = channel.eventLoop.scheduleAtFixedRate(new Runnable() { @Override public void run() { //邏輯代碼,非耗時任務 } }, 6, 6, TimeUnit.HOURS); ....
如果計划任務里面的邏輯比較耗時,那么就不能再用eventLoop,因為這會阻塞IO線程。如果是通過pipeline.addLast(group, "handler", new MyBusinessLogicHandler()); 這種方式添加的業務線程我們可以使用下面的方式添加計划任務方法實現:
***future = ctx.executor().scheduleAtFixedRate(new Runnable() { @Override public void run() { } }, 6, 6, TimeUnit.HOURS);***
...
netty 源碼
public EventExecutor executor() { return (EventExecutor)(this.executor == null?this.channel().eventLoop():this.executor); }
如果this.executor為null,就返回channel().eventLoop(),這個是io讀寫線程,肯定是不能執行耗時任務的。
如果不為空,那么是怎么傳進來的呢?
DefaultChannelPipeline
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) { final AbstractChannelHandlerContext newCtx; synchronized(this) { checkMultiplicity(handler); newCtx = this.newContext(group, this.filterName(name, handler), handler);
private AbstractChannelHandlerContext newContext(EventExecutorGroup group, String name, ChannelHandler handler) { return new DefaultChannelHandlerContext(this, this.childExecutor(group), name, handler); }
通過源碼發現:其實就是我們在添加handler時指定的DefaultEventExecutorGroup。
、所以結論是:如果在處理耗時任務的Handler添加時用到了DefaultEventExecutorGroup是可以 ctx.executor().scheduleAtFixedRate這么用的,但是如果你再添加handler時沒有沒有指定特殊的EventExecutorGroup,是不能執行耗時任務的。
如果是在IO線程,如果想處理耗時任務邏輯,那么就需要新建一個EventExecutorGroup,並調用他的相關方法
EventLoop:其本質是一個用來處理IO事件的線程,EventLoopGroup 其本質是一個線程池。一個EventLoop可以和多個Channel綁定,處理多個Channel的IO事件;但是一個Channel在整個生命周期內只會被一個EventLoop處理,這就也就保證了線程安全。