从0到1构建分布式秒杀系统案例的代码已经所有上传至码云,文章也被分发到各个平台。其中也收到了很多小伙伴喜欢和反馈,有网友如是说:java
说实话,能用上的很少,中小企业都不可能用到,大型企业也不是一我的就能搞起的,大部分人一生都用不上,等有这个须要再搞吧。git
个人观点是赞同但不支持,基本上任何事物都是呈金字塔分布,互联网也不例外,也就是说大部分可能都是普通人,接触不到所谓大厂的应用场景。可是,书到用时方恨少,机会老是留给有准备的人的,除非有钱难买我乐意,只能说大千世界,每一个人都有本身的生活方式,尊重并活着。算法
前面都是扯淡,也不是什么铺垫,在聊线程池以前咱们最好简单了解下什么是进程,什么是线程,进程和线程到底有什么区别?spring
这里咱们,搬运下某百科的释义:数据库
进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操做系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。tomcat
固然,知乎上也有很多网友的回答,每一个人都有本身不一样的理解方式。这里咱们拿Tomcat容器作例子:你能够这么理解,运行中的Tomcat容器就是一个进程,而每一个用户的操做(查询、上传)能够当作一个或者多个线程。服务器
秒杀活动中,瞬时并发是很是大的,若是每个请求都开启一个新线程,系统就要不断的进行线程的建立和销毁,有时花在建立和销毁线程上的时间会比线程真正执行的时间还长。而且因为硬件条件限制,线程数量又不能无限建立。网络
那么线程池到底解决了那些问题:并发
调用ThreadPoolExecutor的execute提交线程,首先检查CorePool,若是CorePool内的线程小于CorePoolSize,新建立线程执行任务。分布式
若是当前CorePool内的线程大于等于CorePoolSize,那么将线程加入到BlockingQueue。
若是不能加入BlockingQueue,在小于MaxPoolSize的状况下建立线程执行任务。
若是线程数大于等于MaxPoolSize,那么执行拒绝策略。
为了方便测试,咱们在Control中定义了线程池,来模拟用户秒杀动做:
定义初始线程数:
private static int corePoolSize = Runtime.getRuntime().availableProcessors();
复制代码
定义Executor:
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, corePoolSize+1, 10l, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(1000));
复制代码
corePoolSize用于指定核心线程数量
maximumPoolSize指定最大线程数
keepAliveTime和TimeUnit指定线程空闲后的最大存活时间
workQueue则是线程池的缓冲队列,还未执行的线程会在队列中等待,监控队列长度,确保队列有界;不当的线程池大小会使得处理速度变慢,稳定性降低,而且致使内存泄露。若是配置的线程过少,则队列会持续变大,消耗过多内存;而过多的线程又会 因为频繁的上下文切换致使整个系统的速度变缓——殊途而同归。队列的长度相当重要,它必须得是有界的,这样若是线程池不堪重负了它能够暂时拒绝掉新的请求。
ExecutorService 默认的实现是一个无界的LinkedBlockingQueue。
以上只是为了测试方便,模拟出的数据。真实的生产环境,咱们要接入Nginx和Tomcat来处理用户的请求。而Tomcat做为一名容器也是有本身的一套链接池的,做为开发人员你并不须要本身去实现。
Tomcat默认使用自带的链接池,这里咱们也能够自定义实现,打开/conf/server.xml文件,在Connector以前配置一个线程池:
<Executor name="tomcatThreadPool" namePrefix="tomcatThreadPool-" maxThreads="1000" maxIdleTime="300000" minSpareThreads="200"/>
复制代码
name:共享线程池的名字。这是Connector为了共享线程池要引用的名字,该名字必须惟一。默认值:None;
namePrefix:在JVM上,每一个运行线程均可以有一个name 字符串。这一属性为线程池中每一个线程的name字符串设置了一个前缀,Tomcat将把线程号追加到这一前缀的后面。默认值:tomcat-exec-;
maxThreads:该线程池能够容纳的最大线程数。默认值:200;
maxIdleTime:在Tomcat关闭一个空闲线程以前,容许空闲线程持续的时间(以毫秒为单位)。只有当前活跃的线程数大于minSpareThread的值,才会关闭空闲线程。默认值:60000(一分钟)。
minSpareThreads:Tomcat应该始终打开的最小不活跃线程数。默认值:25。
配置Connector:
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" minProcessors="5" maxProcessors="75" acceptCount="1000"/>
复制代码
executor:表示使用该参数值对应的线程池;
minProcessors:服务器启动时建立的处理请求的线程数;
maxProcessors:最大能够建立的处理请求的线程数;
acceptCount:指定当全部可使用的处理请求的线程数都被使用时,能够放处处理队列中的请求数,超过这个数的请求将不予处理。
代码案例:从0到1构建分布式秒杀系统