从0到1构建分布式秒杀系统案例的代码已经全部上传至码云,文章也被分发到各个平台。其中也收到了不少小伙伴喜欢和反馈,有网友如是说:
说实话,能用上的不多,中小企业都不可能用到,大型企业也不是一个人就能搞起的,大部分人一辈子都用不上,等有这个需要再搞吧。
我的观点是赞同但不支持,基本上任何事物都是呈金字塔分布,互联网也不例外,也就是说大部分可能都是普通人,接触不到所谓大厂的应用场景。但是,书到用时方恨少,机会总是留给有准备的人的,除非有钱难买我乐意,只能说大千世界,每个人都有自己的生活方式,尊重并活着。
前面都是扯淡,也不是什么铺垫,在聊线程池之前我们最好简单了解下什么是进程,什么是线程,进程和线程到底有什么区别?
这里我们,搬运下某百科的释义:
进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
当然,知乎上也有不少网友的回答,每个人都有自己不同的理解方式。这里我们拿Tomcat容器做例子:你可以这么理解,运行中的Tomcat容器就是一个进程,而每个用户的操作(查询、上传)可以当做一个或者多个线程。
秒杀活动中,瞬时并发是非常大的,如果每一个请求都开启一个新线程,系统就要不断的进行线程的创建和销毁,有时花在创建和销毁线程上的时间会比线程真正执行的时间还长。并且由于硬件条件限制,线程数量又不能无限创建。
那么线程池到底解决了那些问题:
为了方便测试,我们在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));
以上只是为了测试方便,模拟出的数据。真实的生产环境,我们要接入Nginx和Tomcat来处理用户的请求。而Tomcat作为一名容器也是有自己的一套连接池的,作为开发人员你并不需要自己去实现。
Tomcat默认使用自带的连接池,这里我们也可以自定义实现,打开/conf/server.xml文件,在Connector之前配置一个线程池:
<Executor name="tomcatThreadPool"
namePrefix="tomcatThreadPool-"
maxThreads="1000"
maxIdleTime="300000"
minSpareThreads="200"/>
配置Connector:
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
minProcessors="5"
maxProcessors="75"
acceptCount="1000"/>
代码案例:从0到1构建分布式秒杀系统