consumer的DubboClientHandler线程池
1. 创建线程池
创建线程池的调用栈如下:

SimpleDataStore把线程池存放在map中。
public class NettyClient extends AbstractClient {
public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException{
//首先调用父类的wrapChannelHandler方法,创建DubboClientHandler线程池
super(url, wrapChannelHandler(url, handler));
}
}
public abstract class AbstractClient extends AbstractEndpoint implements Client {
protected static final String CLIENT_THREAD_POOL_NAME = "DubboClientHandler";
//DubboClientHandler线程池
protected volatile ExecutorService executor;
public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {
//省略其他非相关代码
//从SimpleDataStore中获取线程池
executor = (ExecutorService) ExtensionLoader.getExtensionLoader(DataStore.class)
.getDefaultExtension().get(Constants.CONSUMER_SIDE, Integer.toString(url.getPort()));
ExtensionLoader.getExtensionLoader(DataStore.class)
.getDefaultExtension().remove(Constants.CONSUMER_SIDE, Integer.toString(url.getPort()));
}
protected static ChannelHandler wrapChannelHandler(URL url, ChannelHandler handler){
//给线程命名
url = ExecutorUtil.setThreadName(url, CLIENT_THREAD_POOL_NAME);
url = url.addParameterIfAbsent(Constants.THREADPOOL_KEY, Constants.DEFAULT_CLIENT_THREADPOOL);
return ChannelHandlers.wrap(handler, url);
}
}
public class WrappedChannelHandler implements ChannelHandlerDelegate {
protected final ExecutorService executor;
public WrappedChannelHandler(ChannelHandler handler, URL url) {
this.handler = handler;
this.url = url;
//此处创建了线程池
executor = (ExecutorService) ExtensionLoader.getExtensionLoader(ThreadPool.class)
.getAdaptiveExtension().getExecutor(url);
String componentKey = Constants.EXECUTOR_SERVICE_COMPONENT_KEY;
if (Constants.CONSUMER_SIDE.equalsIgnoreCase(url.getParameter(Constants.SIDE_KEY))) {
componentKey = Constants.CONSUMER_SIDE;
}
DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
dataStore.put(componentKey, Integer.toString(url.getPort()), executor);
}
}
executor = (ExecutorService) ExtensionLoader.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);
ThreadPool$Adpative代码如下:
package com.alibaba.dubbo.common.threadpool;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class ThreadPool$Adpative implements com.alibaba.dubbo.common.threadpool.ThreadPool {
public java.util.concurrent.Executor getExecutor(
com.alibaba.dubbo.common.URL arg0) {
if (arg0 == null)
throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg0;
// url中的默认参数threadpool=cached
String extName = url.getParameter("threadpool", "fixed");
if (extName == null)
throw new IllegalStateException(
"Fail to get extension(com.alibaba.dubbo.common.threadpool.ThreadPool) name from url("
+ url.toString() + ") use keys([threadpool])");
com.alibaba.dubbo.common.threadpool.ThreadPool extension =
(com.alibaba.dubbo.common.threadpool.ThreadPool) ExtensionLoader
.getExtensionLoader(com.alibaba.dubbo.common.threadpool.ThreadPool.class)
.getExtension(extName);
return extension.getExecutor(arg0);
}
}
CachedThreadPool类:
/**
* 此线程池可伸缩,线程空闲一分钟后回收,新请求重新创建线程
*
*/
public class CachedThreadPool implements ThreadPool {
public Executor getExecutor(URL url) {
String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);
int cores = url.getParameter(Constants.CORE_THREADS_KEY, Constants.DEFAULT_CORE_THREADS);
int threads = url.getParameter(Constants.THREADS_KEY, Integer.MAX_VALUE);
int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);
int alive = url.getParameter(Constants.ALIVE_KEY, Constants.DEFAULT_ALIVE);
return new ThreadPoolExecutor(cores, threads, alive, TimeUnit.MILLISECONDS,
queues == 0 ? new SynchronousQueue<Runnable>() :
(queues < 0 ? new LinkedBlockingQueue<Runnable>()
: new LinkedBlockingQueue<Runnable>(queues)),
new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url));
}
}
2. 往线程池投送任务
线程池创建之后,是谁在什么时候往里面扔任务呢?

public class AllChannelHandler extends WrappedChannelHandler {
public void received(Channel channel, Object message) throws RemotingException {
ExecutorService cexecutor = getExecutorService();
try {
//往线程池扔任务
cexecutor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
} catch (Throwable t) {
throw new ExecutionException(message, channel, getClass() + " error when process received event .", t);
}
}
private ExecutorService getExecutorService() {
//executor在父类WrappedChannelHandler中
ExecutorService cexecutor = executor;
if (cexecutor == null || cexecutor.isShutdown()) {
cexecutor = SHARED_EXECUTOR;
}
return cexecutor;
}
}
也就是说nio线程往DubboClientHandler线程池扔任务,DubboClientHandler线程再唤醒等待的consumer调用线程。
3. 线程池执行任务

consumer的DubboClientHandler线程池的更多相关文章
- Mysql线程池优化笔记
Mysql线程池优化我是总结了一个站长的3篇文章了,这里我整理到一起来本文章就分为三个优化段了,下面一起来看看. Mysql线程池系列一(Thread pool FAQ) 首先介绍什么是mys ...
- java中线程池的使用方法
1 引入线程池的原因 由于线程的生命周期中包括创建.就绪.运行.阻塞.销毁阶段,当我们待处理的任务数目较小时,我们可以自己创建几个线程来处理相应的任务,但当有大量的任务时,由于创建.销毁线程需要很大的 ...
- Java 线程池详细介绍
根据摩尔定律(Moore’s law),集成电路晶体管的数量差不多每两年就会翻一倍.但是晶体管数量指数级的增长不一定会导致 CPU 性能的指数级增长.处理器制造商花了很多年来提高时钟频率和指令并行.在 ...
- Java:多线程,线程池,使用CompletionService通过Future来处理Callable的返回结果
1. 背景 在Java5的多线程中,可以使用Callable接口来实现具有返回值的线程.使用线程池的submit方法提交Callable任务,利用submit方法返回的Future存根,调用此存根的g ...
- python系列之 - 并发编程(进程池,线程池,协程)
需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ...
- python 多线程 及多线程通信,互斥锁,线程池
1.简单的多线程例子 import threading,timedef b_fun(i): print "____________b_fun start" time.sleep(7 ...
- python全栈开发 * 线程队列 线程池 协程 * 180731
一.线程队列 队列:1.Queue 先进先出 自带锁 数据安全 from queue import Queue from multiprocessing import Queue (IPC队列)2.L ...
- Day037--Python--线程的其他方法,GIL, 线程事件,队列,线程池,协程
1. 线程的一些其他方法 threading.current_thread() # 线程对象 threading.current_thread().getName() # 线程名称 threadi ...
- (并发编程)进程池线程池--提交任务2种方式+(异步回调)、协程--yield关键字 greenlet ,gevent模块
一:进程池与线程池(同步,异步+回调函数)先造个池子,然后放任务为什么要用“池”:池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务池子内什么时候装进程:并发的任务 ...
随机推荐
- Android实践项目汇报(总结)
天气客户端开发报告 1 系统需求分析 1.1功能性需求分析 天气预报客户端,最基本就是为用户提供准确的天气预报信息.天气查询结果有两种:一种是当天天气信息,信息结果比较详细,除温度.天气状况外还 ...
- bzoj 2654 tree - 二分法 - 最小生成树
给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示点数,边数和需要的白色边数. 接下来E行,每行 ...
- Win32建立右键弹出菜单(PopMenu)
自定义右键菜单: #ifndef _CONTEXTMENU_H_ #define _CONTEXTMENU_H_ #include <windows.h> //动态菜单 #define I ...
- Java求两个数平均值
如何正确的求2个数的平均值.在练习算法二分查找的时候发现的,以前没有注意到的bug 备注:数据以int类型为例 一.以前的通用写法 /** * 求a+b平均值 * @param a * @param ...
- Go第四篇之流程控制
流程控制是每种编程语言控制逻辑走向和执行次序的重要部分,流程控制可以说是一门语言的“经脉”. Go 语言的常用流程控制有 if 和 for,而 switch 和 goto 主要是为了简化代码.降低重复 ...
- 3、CommonChunkPlugin提取公共js-以提取一个jquery为例
cnpm install css-loader --save-dev //css-loader 是将css打包进js cnpm install style-loader --save-dev ...
- Wireshark无法解析OpenFlow配置协议 解决方法
在使用wireshark对OpenFlow交换机与FlowVisor的通信过程进行抓包分析的时候,在其选项中有openflow_v1选项,但Wireshark竟无法解析OpenFlow协议. 在查阅相 ...
- FAST Hello World - Preparation for software's running environment
Ubuntu 14.04 安装 libpcap-1.1.1 & libpnet-1.1.4 & NMAC function lib 参考: NetMagic.org yacc: com ...
- 【TCP/IP详解 卷一:协议】第二十三章 TCP的保活定时器
本章介绍保活定时器. 在 TCP 的三握四挥 章节中,我们介绍了 处在 TIME_WAIT 的 2MSL定时器:在 TCP的超时与重传 章节中,我们介绍了 重传定时器:在上一章节中,我们介绍了 防止死 ...
- vscode中使用EF脚手架生成数据库上下文(scaffold-dbcontext)
目前在vscode上用netcore + ef core,在用dbfirst的方式生成模型和context上下文一直没有找到方法,之前在vs2017中,的nuget管理控制台输入命令: Scaffol ...