粉丝9572获赞6.8万

县城池一旦初始化之后,他的参数还能再修改吗?那又如何动态的修改县城池的参数呢?首先我们了解一下县城池的三个核心参数是核心县城数,最大县城数,还有工作队列。 为什么这三个参数是核心的呢?因为这三个参数他决定了宣传时钟的任务的执行流程。 如何支持参数的动态配置呢?啊?我们看 three 的 pro is q 的,他提供了一些方法,看到有获取核心形成数的方法,还有设置核心形成数的方法,有获取最大形成数的方法,有设置最大形成数的方法, 也就是核心建成数和最大建成数都可以通过已有的方法来进行动态的设置啊。需要注意的是,在程序运行期间啊,如果调用 设置横线竖这个方法的时候,线程尺会首先判断当前工作线程是否大于要设置的横线竖,如果大于的话,就会回收工作线程。然后接下来我们看这个工作对列 看,他提供了一个该得 q 这个方法来获取限能时的工作队列与任务队列啊,但是并没有给他设置容量的方法。嗯,看到林克特不能更贵,它里面的容量是使用翻动所修饰的 啊,所以一旦被初始化之后,后续就不能修改这个任务队列的容量。美团的方式他是自定义了一个类啊,叫做 recessable compensated link to broken k 这个队列也就是复制了一份,他把这个 compensate 这个属性变为可变的,把翻到给去 去掉提供了盖子赛的方法,他就变为可变容量的 inclusive pro 跟盔,然后通过 three 的 pro eq 的啊,注入自定义的这个对列 啊,之后如果想动态的修改他的容量的话,可以通过该的 care 方法来获取对列,然后通过 set capcity 啊来设置他的容量,这样就实现了动态的设置对列的容量 啊。这是美团的一个做法啊,如果我们项目也想实现这种效果的话,可以借助县城的开元项目 hyperfog 啊,义乌县城持框架, 支持新增池动态变更监控报警,无需修改代码,轻松引入,支持多种使用模式,致力于提高系统运行保障能力啊。或者是单内 mac tp 轻量级动态线程尺内置监控告警功能,集成第三方中间键线程尺管理啊,可以基于主流的配置中心,支持 nicos, rookipo 等等啊,也可以通过 spi 自定义实现。

大部分人可能都知道,在实际的开发中用到县城的地方,我们一般不直接 newslett 去创建一个县城, 当然也不建议去用 executives 中的自带的这几个线程池,所以大部分情况下我们都会向上图这种方法去自定一个线程池去使用。那么线程池中的这些核心参数你都真正理解是什么意思了吗?接下来我们详细探讨一下。 第一个参数是 corporate size, 它的意思就是说是核心现成数,看图中我框起来的这部分文字解释其实应该已经很清楚了。 第二个参数的意思呢?就是说最大形成数,表示当前现成时最多可以有多少个现成去执行任务。第三个和第四个参数一般是合起来使用的,一个表示 具体的数值,一个表示这个数值的单位,他就表示核心县城的空闲时间大概是多久,超过这个时间就会被销毁。 walk king 表示任务队列及存放我们提交任务的一个队列。 stride factory 是县城工厂,一般的话我们使用它主要是用来创建县城的,可以对当前的县城做一些定制,比如说起一些我们自己的名字,然后做一些其他方面的一些处理。 我们可以看一下这里是我自定义的一个县城,它里边主要是实现这个牛 sir 的方法,我们去创建一个 siri 就好了。 最后一个是拒绝策略及当前现成尺满了的话,新来的任务该怎么去处理?这里我使用的是现成尺自带的拒绝策略,当然我们也可以替换成我们自己想要的 策略在里边作为根据我们实际的业务场景去定制一些拒绝策略。县城池自带的四种拒绝策略,如下图框出来的绿色主食部分,我们接下来可以详细看一下每个拒绝策略是怎么实现的。 这是第一个线程,我们可以看到他的策略是把当前的线程交给主线程去执行及执行线程时任务提交的那个线程去执行。第二个策略是直接抛出一个异常, 第三个策略是什么也不做,极意味着丢弃这个县城。第四个策略则表示移除当前任务队列对手的那个任务,然后再重新提交当前这个任务。 以上就是现成十几个核心参数的一个介绍,这里我们看一下整体的一个总结。接下来我们再用一个实际的问题来感受一下这些参数实际的意义 作用。如上图红色哐哐哐出来的这个问题。首先他会创建五个核心线程去执行前五个任务,从第六个任务开始来的,都会放到任务队列中。 当任务队列放满以后,那么当前县城池中一共就有五十五个任务,当地五十六到六十个任务来了以后,会继续创建县城去执行,因为这个时候我们只创建了五个县城吗?我们最大限程数是十,所以还可以再创建五个。 截止目前为止,县城池中已经创建了十个县城,达到最大县城数限制。然后任务队列中也已经有五十个任务了,也达到了任务队列的限制,所以当年县城池已经满了, 这个时候第七十个到一百个。这四十个任务来了以后,有些人吃已经处于满载状态,所以他们会去执行拒绝策略了,这里 有给的拒绝策略是抛出一场,所以他会抛出四十个亿场。接下来我们验证一下我们所说的结论。首先在这里我自定义一个现成池,然后具体参数如上面所施, 其中县城工厂,我这里边自定义的一个县城工厂,我们可以看一下,主要给他的就是说起了一个名字,然后还有一个计数器, 主要方便我们在打印县城的时候,可以看到这是我们自定义的县城,还有他是第几个县城,然后拒绝策略在这里我也采用的是自定义的,这里采使用那个说出一段话来模拟抛出异常吧, 这里也用了计数器,所以刚才按照我们的结论,应该会这个计数器到四十。下面这段代码是提交一百个任务,并且其中可以看到每个 任务就是模拟呃执行三十三十秒,最后一行是获取当前任务队列中的任务数。 接下来我们执行一下,可以看到县城一共是有十个没有问题,然后拒绝策略的话,一共他是有四十个,也是没有问题的, 然后队列中的任务数是五十个,所以说呢,再来看我们上面的这个结论,他是结果是按照我们的想法来执行的,你还有什么问题吗?欢迎留言。

ok, 紧接着呢,咱们来看这样一道面试题,来自于阿里的啊,现成池使用完毕,为何必须执行沙荡方法?那当然也可以执行沙荡闹方法。呃,他对标的薪资呢,一般在二十到三十 k 左右,岗位呢,也是中高级开发工程师。 那首先这个问题咱们要清楚,如果我在使用完毕线程值之后,没有及时的去调用砂档或者砂档闹方法,会造成什么问题? 那咱们都清楚啊,县城时在帮咱们去处理任务的时候呢,他的内部会帮咱们启动一个县城,而启动县城的方式咱们可以看之前看过的 add worker 方法, 在 a d d work 方法中咱们可以看到,哎,其实他的工作线程也是基于死锐的对象 去执行了一个 star 的方法,然后呢,这种线程它本身就会占用一个训练基站,而这种训练基站的话呢,要清楚啊,他在咱们的 j m 层面中属于 j c 弱者, 那根据咱们的可达性分析算法,这个线程他就不可能被回收,他会一直占用着咱们的 j v m 内存的资源, 那这样的话就会造成一个问题,你没有及时的执行沙荡和沙荡荡。 ok, 我构建的所有县城,只要是核心的,他永远都不会被回收,那这样的话就会造成一个内存泄露问题。 好,除了咱们现成的内存泄露之外呢,还有另外一个问题,什么呢?一定要注意啊,这里在现成池中启动工作,现成时是基于你 work 对象内部的 死锐的去启动的,而当我执行 t 点 star 之后,它会执行我 worker 对象当中的乱方法, 而在 run 方法中会执行 run worker, 而在 run worker 内部传入了 this, 而这个 this 属于我当前的 worker 对象,那么这样的话就可以理解为我启动的线程还指向着我的 worker 对象,我的 worker 对象也是不能被回收的。同时 worker 对象属于现成池的内部类,你内部类都没有被回收的话,你的外部类也没有办法被回收,就会造成我的整个现成池对象也不会被回收。 所以说最终啊,咱们可以确定一点,如果说你没有在使用完 b 现成池之后及时的调用砂当或者砂当当方法的话呢,很有 可能造成你的整个县城池对象都没有办法被这些回收,从而占用咱们的堆内增资源很严重。那如果说这种县,这种县,这种县城池啊,你这个一直都没有去执行杀到,那最终肯定会造成一个内存泄露的问题, 那解决这个问题的方式也很简单,看题目就知道了,只要执行杀到或者杀到闹方法就可以了。那这个方这个问题是怎么去解决的?其实呢,前面已经把他的核心点说出来了, 就是你的核心线程没有被回收掉吗?那当咱们去执行沙特当方法的时候,可以看到他做了两点很重要的事情,第一点,他把现成时的状态从软拧改为了沙特当,而当这个位置改为沙当之后呢, 咱们所有阻塞的工作线程在前面会有一个判断,而这个判断呢,通过刹道就可以直接跳出获取任务的过程了,也就是咱们的核心线程在执行完毕一个任务之后,要通过这个 get task 方法,尝试从阻塞对列中拉取任务。 而在拉取任务的时候呢,这边可以看到,如果是非核心, ok, 我走他的处方法,只要阻塞一段时间没有任务,我就直接结束掉当前线程。 但如果是核心县城,我会执行 take 方法,而这个 take 方法呢,永远都不会被回收,他会一直在这边等着,直到有任务传进来才可以。 而在前面啊,执行到这个方法之前,有一个判断,如果说你现成值的状态已经大于 等于杀当,并且你的阻塞对列当中已经没有任务了,那么我会直接到这 啊,直接结束我的 get 他这个方法。我不会继续往下走,到咱们当前的 take 方法这个位置。所以说,咱们刚才看到的杀他当方法,杀他当, 哎,哎, id 卡住了,好,当咱们执行杀当方法之后,更改了现成池状态变为杀当之后,那么咱们的工作现成就不会再往下走,走到 take 方法了。 哎,但是啊,我有的县城可能已经走到了这个方法,正在阻塞,那怎么办呢?所以说他还有第二个操作,他执行了一个叫做 interrupt workers 的方法。在这个方法内部,他会做一个事情,把所有 的没有正在运行任务的工作线程,直接把他的中段标记位设置为主。 而当中断标记位设置为处之后呢,咱们在 gettask 中,已经执行到 take 方法的线程就会被唤醒了。说白了,我阻塞时会挂起线程,而当线程中断之后,我会被唤醒,那我就会继续向下走,重新循环。走到这个位置之后,你会发现,哎,状态改变了, 状态改变之后,我依然可以通过这个状态的判断退出咱们的 get task 方法,而最终在咱们的 run worker 方法内部就会退出我的 wifi 循环,因为这边反复的是个闹。 退出 vivo 学员之后呢,正常地做一些后续的处理,然后最终返回到我 worker 对象当中的软方法软窝可结束了。软方法结束了,现成自然也就结束了。那同样的,如果你执行了沙特荡闹方法,他会更加彻底。来看一下咱们的沙特荡闹 在杀到闹方法里面呢,同样的,他第一个事情把状态改为 stop, 而这个状态改为 stop, 跟之前的状态改为杀到有异曲同工之妙。都是一样的,县城在执行到库或者是 take 方法之前,先会判断县城值的状态, 只要状态不是 running, 我都会直接结束啊。那么还有另外一个情况,那正在阻测怎么办呢?你会发现它的 interrupt rocks 方法会更加彻底。我不管你的工作现程正在做什么事情,我直接执行这个中断方法,让你的 工作线程直接中断啊,直接中断。除了你工作线程刚刚在创建的时候,我没有办法中断你。但是无论是正在执行任务的,还是准备去组织队列获取任务的,或者是正在组织队列尝试获取任务的线程,我都直接把你中断。那这样一来, 咱们的工作线程就可以以一个比较快的速度去结束掉他的生命周期。那这样一来,工作线程没了 work 对象就没有指向了。 worker 对象没有指向之后, srid pro execute 现成值对象也没有指向了,那这样才可以被 g c 正常的回收。 那这就是咱们关于这个问题,现实为何必须要执行杀到,先阐述清楚不杀到会出现什么问题,其次执行了杀到或者杀到闹之后,他是如何帮我解决这个问题的?

自研美团动态现成池我这边先给大家演示一下我的动态现成池的一个效果,比如说我这边,呃,就有一个 user 应用啊,看下面 user 应用,它就是一个很简单的 spring boot, 然后呢,有一个周瑜看错了啊,里面呢,就注册了一个,注入了一个周瑜 service, 解释下面这个类。然后呢,哎,我这里又去定义了一个新成词啊,这里 p e 为什么叫做 p e, 我等下来解释,你可以改名字啊,不是说非得叫 p e, 所以说这个现成池啊,当我在处理 text 请求的时候,我就可以利用这个现成池去执行我的一个任务啊,包括我们现成池 本身你可以怎么用,那么我们我们这边都可以怎么用,最终我就返回。当然我们这里的配置文件其实也很简单,就是去连了一下 lacos, 那为什么要连 lcos 呢啊?大家等一下就能够知道了。关于这个问题的详细 文字版,我已经整理了一份八十万字的抓名师大全笔记,放在视频的最后面,坚持看完一定对你有关注。所以我先演示一下效果,比如说我启动我们当前的 u 的应用啊,因为在我们呃, ctrl 这边,我们这里会去获取呃,这个泰式的方法返回值以及我当前县城池里面核心县城数的大小啊,那么,呃,我们来试一下,到我们的这边来访问一下泰式的。 好,你看我这里访问成功没有问题,所以说请求肯定是能够正常的执行的,而且我们发现我们现在线程词的核心线程数是二十,那么我们刚刚不是连了一下呃, napos 嘛?呃, napos 呢?我们这边就会去读取 d t、 p, 也就是动态线程词的这个缩写等 对应的样品键,那么我这边就已经提前配好了,那么我们可以来看一下我们里面的配置是这样子的,所以我们这个配置相当于就是配置了两个性能池,所以说你既然能够配置两个,那你肯定可以支持配置一个或者支持更多,而且我的名字叫做一个叫做 p 一,一个叫做 pr, 就是我们可以去修改的改成你想要的名字。并且我这里也去订立了说,呃,你 pe 线程时的核心线程数是二十,最大线程数是五十,所以说我们刚刚在访问泰式的时候,因为我用的就是 p, 说这里打印出来的就是二十,那如果说我现在把它的改成二十五来,注意看,我只要修改发布,哎,我并不需要去重启我们的应用,那么我们现成时的核心现成数他其实就发生了改变,看到没再来一次,比如说我再来把它改成 三十,发布,确定,确认发布,然后确定,然后我们再来访问一下,这开始的他就变成了三十,而在这个过程间我并没有去重启我们的应用,所以这种我们动态性能值的效果,你可以根据你当前应用的情况 去动态的去修改某一个线段词,他对应的这些阐述所以说是非常灵活以及呃是非常有实际意义的。好,那么呃,我们,呃这样做, 老师我写的这个动态性能值,他到底是有哪些关键的点呢?我们来看。首先我们要去分析动态性能值什么时候创建的好?我可以来带大家看一下我的代码, 比如说我当前 user 应用,我就依赖了一个 springboard start, 然后呢就依赖了我上面写的这个动态性能词的 start, 也就是上面这个项目,那么在这个项目里面我就去定义了一个自动配置类,而在这个自动配置类里面其实定义了很多东西,那么其中跟我们性能词对象创建的其实这个类, 因为在这个类里面我通过呃去注册了一个病例分类型,就相当于像我们食品溶剂里面去订立了一个病,这个病的类型叫做 d t p exq, 那么他呢,其实就是继承了我们思维的 point 的,所以说你可以就把他们两者理解为同样的一个就可以了。好,所以说,呃,相当于你看我这里会去根据你当前的配置,比如如果说你配了两个 p 一 p 二, 那么我们就会去生成两个 d t p execute 这个病,两个病对象,懂吗?同时呢我也会根据你的配置去向我们现成池的对应的这些参数去去复制啊,所以是这一个最终我们,呃,因为在我们刚刚这里构成方法的第一个参数和第二个参数啊,那么最终就是我现成池的 有些新人数和最大新人数,就是我们在构建这个病的时候,我就向构造方法参数去指定的值和这个值的来源,就是我们配置的里面的来源啊,所以说,呃,最终我们构建出来 的现成词的并对象也就创建出来了,而且对应的参数也就设置好了,就是这个,所以说当我们在 ctrl 里面,你可以通过这种方式来进行注入啊,注入的对象其实实际上就是我们刚刚讲的 d, 呃, d t p 的这个对象,因为它的负类是 sweet pro, e 是 q 的,所以说我们代码这么写是 ok 的,或者你直接写成这个也是 ok 的啊。我是建议大家写的这个,因为这样子你就可以区分 出来,呃,这是动态性能词,而这个呢?呃,其实,呃他因为我们刚刚那个写法的话,他有可能是动态性能词,也有可能是我们的普通性能词,懂不懂?所以说啊,建议大家可以像我刚刚这种写法会更可读一点。 所以这里就分析了我们的现成池是什么时候穿建的,其实就是在十倍勇气启动的时候,呃,过去穿建的,穿建出来对应的现成池的并对象。然后呢,再看下一个问题,那动态现成池的参数是如何设置的啊?我们刚刚讲了,其实在创建并对象的时候,其实就会去设置好参数,根据你发货池里面的配置去设置好参数。 那还有一种情况,就是像我们刚刚演示的过程,中间如果说我 locos 里面的配置发生了更新哦,那么这个最终是怎么生效的呢?其实就跟我们刚刚的有一个 listen 的有关系,也就是利用了 locos 的接听器,如果 locos 呃某个文件里面的配置发生了变化,其实就会触发这个方法,而我最终就可以拿到最新 的配置,那么我就可以按照对应的关系去修改我们县城池里面对应的参数,这样子呢,也就完成了常数的修改,对,就是这个问题,那么再看下一个,那动态县城池,呃有没有对应的监控呢?其实是有的,大家可以发现我这个项目我不停的在打印这些东西,县城池, p e 啊,对应的参数,包括你看这前面的信息,就是打印的我修改之前的信息,那么字体就是相当于监控信息,只不过做的比较粗糙,那么这个监控又怎么实现的呢?还是在我们自动配置店里面,我订立了一个 ddp monitor, 就是一个监控器,它是一个 abligation run, 相当于我们 smart 启动完了之后会掉这个乱方法,而这个乱方法里面他就开启了一个定时任务,对不对?而具体定时任务的逻辑呢,就是这个方法,来这个方法里面他就会去读取你当前所有的呃现成纸的对象,去获取你当前现成纸的名字以及你对应的参数。对,这样子就是这是监控信息, 同时我这里还有一个告警,其实也是在看看这个地方,呃,告警啊,你看他下面也是一个定时任务,他会定时的去执行我们这个告警的方法,而告警的逻辑呢啊也是去获取我们呃所有的动态性能词对象,然后呢去获取你当前性能词,你总共 就有有多少个县城,对,然后去看当前县城值的个数为啊是不是超过了告警的预值,就说这里有个 max, 这是呃我们呃后续要支持的去设置的一个告警的预值,就是当你县城市里面的县城超过了这个 max, 那么我就要告警,只不过我现在是通过打印语句 告警的,我们可以去连接邮件,我们可以去连接短信,可以去连,呃,连接,呃公众号呀,或者电话什么的都可以来实现这个告警的功能啊。就说,呃,这都是通过这个定时任务来进行实现的啊。所以这是我们监控和告警其实也都有相应的简单版本的实现。那么,呃,所以说这是我们关于动态性的 时的几个要点吧。所以说关于动态性认识,呃,具体怎么实现的,我这里就不花时间去看这些代码了啊。我相信通过我刚刚讲的几个点,大家,呃,如果拿到这个代码之后自己去看相关的代码,其实应该也都是能够呃看得懂的,好吧,所以说,呃,这个视频也就讲这里吧。

大家好,今天用现成词优化了一段代码,查询速度提高了将近一倍,我模拟了一下这个情况,这里有一个关键词,然后调用搜索方法,最终把结果打印一下。那搜索方法里边呢,要调用两个接口,一个是用来查询商品,一个是用来查询店铺, 最终把结果合并返回一下,我们来试一下,大家看一千六百多毫秒,那这个时间呢?相当于这两个接口调用的总时间加一起。 但其实呢,这两个接口返回的数据之间是没有依赖关系的,也就是说先吊谁后吊谁是没有关系的。所以针对这种情况,我们是可以用现成词来做一个并行的查询,我们试一下把它改成二,然后呢调 用四尺二,接下来我们改这个方法就行了,首先呢我们准备一个线程尺,我们用这个定长的 fans 的就行。 好,然后呢做两个县城,三个 mite, 好,两个县城,然后呢给他们做一个沙子档,最重要的是要做一个鹅位置, 等待这两个县城结束。超市时间呢,我们就设一个最大的吧,相当于不设了,然后 tmunize 点迷你的分钟,然后处理一下异常。好,那框架呢就写好了,我们在上面先准备一个 rea, 然后在下边返回, 然后这两个县城一个是用来查询店铺,一个是用来查询商品,我们先来这个商品的, 然后在这填充到锐灶它里面塞他肚子,然后呢查询店铺, 然后呢我们把这个软皂他返回就可以了啊,这个就有了,把这个去掉就行了。好,我们再来试一下, 大家看九百多毫秒,好,今天就到这里,谢谢大家,再见。

呃,能简单聊一下现实是大巧是如何设置的吗?呃,呃,那个 cpu 那个密集任何家居嘛?然后他也是那个 ios 级任务二 m 嘛?嗯,第一个说明他第一个那个加一的话,那个他这种任务的话,呃他销售的主要是那个 cpu 的这个资源,呃,可以加上现实社会主义的那个单位的 cpu 和艺术加一,然后呃比那个 cpu 和进口勾出来的一个建, 他是呃为了保持现在我们班的那个区域中断,呃或者是其他原因的话导致的那个任务的暂停引导。大家跟你一样,呃, 一旦那个他那个任务暂停的话,那个 cpu 可能就会出现一个空间状态,然后呃在里面那种情况下,他多出来的那个健全,就 可以充分运用到这个 cq 的空间时间段。那第二个呢?有一个,呃密集的二维码,那这种任务运用起来的话,它系统会用大部分的这个时间来处理 io 胶布,那这个限制的话在自己这个 io 的时间,现在,呃不会占用 cq 它去处理,也就是说可以将这个 cq 掉, 要出去给西安组建的补贴。所以的话,那个在 lv 系统的这个应用当中啊,比我们可以用这种解决人。对,具体的这个自动挡应该是二用。对, 嗯,两种你都有提到。那。呃如何来判断是 cpu 密集任务还是 io 密集任务呢?呃, cpu 进行一个简单理解,它是一直利用那个 cpu 计算能力的任务嘛。就比如你在那个类似中,呃对大量的数据进行排序,那分别是起到哪个网络主体的或者是本店主体的这类,它这些都是让你死心。 视频任务呢?测点就是呃 cp 的成交耗费的时间嘛。那相比于这个等待 io 的操作馆的时间会少很多,所以大部分时间都会花在这个等待 io 的操作馆里。嗯,我开好了。

再来看一下这个面试题啊,现成词中主色对列,嗯的作用是什么? 呃,其实就是考察,就是说我们在这个县城池中啊,为什么要使用主色对列啊?第一个是为什么要使用主色对列?还有呢就是为什么不使用普通的对列,而是要使用主色的对列,这其实是两个问题啊, 还有一个问题呢,紧接着就是紧接着,那么通常的问完前面一个问题,这么个后面这个问题了,马上也会出现啊,那么这个问题就是为什么呢?要先把这个任务添加到队列中,而不是先创建最大县城。我们知道了,在这个县城池里面, 我们的这个最大现成数啊,往往是在在这个队列已经满了的情况下,才会去创建这个最大现成数,所以啊,那么为什么要这么去做,而不是说先呢?先呢就是来了个任务,先把任务处理了,先呢创建 这个啊,最大限成数,对吧?把任务处理了,当这个最大限成数达到了之后,满了之后再去添加队列了,这也是个问题啊。那么对于这个面试题呢,我们其实呢应该了要在这个什么在这个线程时的一些原理,包括他的处理流程啊, 这方面的问题回答的比较好了,那面试官呢,才有可能会去问这个问题,那么如果说你现真实的这个基础没有掌握好的话,那么这个问题呢,可能往往都碰不到啊。当然如果你前面的回答的比较好,那么这个问题呢,马上就会出现好,那么如果这个问题要是不知道怎么来回答的,那么接下来呢,看一下韩飞老师呢怎么来分析这个问题啊? 那么首先我们来看一下这个现成词中啊,这个主色对列,它这个作用是什么?那么你明白了,这个作用呢?实际上呢,就以能够同时还能就能够回答两个问题,那么为什么要使用主色的对列,而不是普通的对列啊?记住,这里有两个问题啊, 好,我们一般的对列啊,就是我们普通的对列,他只能够保证呢,作为一个有限长度的缓冲,也就是说你这个对列呢,只是个简单的容器啊,只是一个简单的容器而已啊。那么如果说我要是超出了这个缓冲容长度啊,就是比如说一个普通对列,我给他一个十的长,十个长度, 那么如果说我来了第十一个任务,还要往这个队列里面去放,这个队列实际上是放不进去的,对不对?放不了了,就无法保留了当前任务啊。但是主色队列不一样, 主色对列他长度虽然只有十,但这个时候如果如果来了第十一个任务,那么这第十一个任务呢,他不是说放不进去,他的会主色在这个地方,他会等在这里,你慢慢他会进入主色状态,而不是说了这个任务放不进去了,就直接就啊没了啊。 所以说这个是主色队列跟我们普通队列的一个啊,最主要的一个区别在这里啊,好,那么这个主色队列在我们县城之中, 它的作用是什么呢?这个主色对列了,他可以帮助我们保证这个县城啊,这个任务中的这个啊,就是没有任务时 主设了这个获取任务的现成就是我们的这个现成之中,不是有这个有这个扩现成吗?对吧?就是我们的核心现成啊,核心现成他是怎么存活的呢?就是比如说我,我要是现在没有任务,没有任务在,那么这些现成在干嘛呢? 对吧?啊?然后有任务来了,我就直接可以把这个县城呢,直接把他取走,对不对?那么这些县城实际上就是通过这个主色对列, 当我们这个任务欠这个任务池中啊,这个主色对列中要是没有任务的话,实际上就是通过的这个主色对列啊,将这个核心线程呢,将他主色在这里,让他呢进入一个位的状态,然后释放了这个 cpu 资源啊,而不是,而不需要我们程序员自己去控制,比如说我,我们一个县, 对吧?如,如果说我这个县城当天要是没事做了,那么我们可能需要自己的去调这个,呃,是例补啊,或者是胃调呀,对吧?调这些方法,那么有了主色主色对列的话,那么这些操作我们都不需要去做,主色对列本身就已经给我们提供了这样的功能啊,好, 然后呢,这个主色对列的话,自还自带了这个唤醒,对吧?你,你不仅仅呢,你不需要去写这个主色的方法,唤醒也不需要啊, 所以说呢,这个主色对列在我们县城池中有一个主要的一个作用,就是什么?就是帮助我们去主色县城,然后呢唤醒县城啊,还有呢就是帮我们呢保存这个任务,把这个任务呢能够保存在我们的这个啊主色队列中啊,那么这个是这个主色队列在我们县城池中的一个作用啊,好,那么第二个问题, 为什么先添加队列,而不是先创建最大县城,对吧?那么这个 问题了,我们呢要现在明白啊,就是我们的这个啊,现成词啊,现成词呢,他在接收的就是我们的这个核心现成数,这个核心现出核心现成数啊,满了的情况下啊,比如说我核心现成数是五个,那么这个时候,比如说我最大现成数了是十个啊, 那么这个时候如果来了第六个任务,比如说我现在了已经有五个任务在这里了啊,运行了,我这个时候来了第来了第六个任务,那么的这个时候他会创建第七个县城吗?不知道他会,他会创建第六个县城吗? 会创建第六个县城来处理这第六个任务吗?啊?他不会啊,不会,而是呢先把这第六个任务呢添加到队列里面去,然后呢当这个队列满了的情况下,如果还有任务来,那么这个时候才是去创建这个最大县城数啊, 那么为什么要这么来设计呢?而不是说直接创建第六个县城来,先把这个任务执行了再说,对吧?这样的话,按照我们的 常常理啊,就是我们常规的想法来来看的话,那么按道理来说你,你创建第六个,直接把这个执行的不就更好吗?你为什么还要把它放到这个对应里面让他去等呢啊?直接创建他的效率不是更高吗?其实这里也可以这么去做, 但是呢我们要来看在我们这个县城池呢,他是怎么样来考虑的?为什么要这么来设计啊?当然你如果按照刚刚说的这种常规思维啊,去设计这个县城池, 呃,说有问题没有了,也没有问题,也是没有问题的。那么来看一下现成词啊,他为什么不这么设计而要采用呢?先放对列,再来创建最大现成数。为什么要这么来设计啊?那是因为呢,在我们 这个县城池中啊,这是在这个县城池中,他去创建这个新县城的时候,去创建这个新县城呢,他是要获取一个全局锁的啊,就是说 我们在创建县城的时候要要获取一个全局锁,所以呢,这个创建县城呢,他本身呢是一个比较耗资源的,要加锁啊,这个时候呢,其他的县城呢,他都得主色,比如说我在创建县城的时候,其他县城都得主色,影响了整体的一个效率,影响整体效率啊,然后呢, 这里呢举举一个简单的例子,为什么说一定要先添加队列再去创建最大县城啊?举个简单的例子给大家解释一下啊。当然呢,我我们讲了另外一种常规设计的也是没有问题的,那么我们来看这两种设计的优劣之分啊, 就好比了,在一个企业里面,比如说我们在企业里面啊,有十个正式员工的一个名额,比如说我这个企业里面啊,这个这个部门,对吧?有十个正式员工的名额,最多了,可以招只有十个正式工,最多可以招十个正式工,对吧?那么这个时候啊, 我们呢,比如说这个部门要是先啊刚刚创立,比如说我这个部门刚刚创立,上面呢,给了你十个名额,那么这个部门你会一上来就招十个人吗?可能不会,对不对?可能呢刚开始了,可能只招那么一两个人,因为这个时候我可能啊,还没有任务了,对不对?我招这么多人,我都没有任务要做,那么招这么多人都养在这里,对不对? 那么这个时候呢,往往呢就是先招那么一两个人,然后等这个任务,对不对?然后来了一个任务,就就招一个来,如果任发现这个任务了,就是 少了人,对不对?然后就招人,少了人就招人,少了人,少了人呢又招人。那么如果我招满了十个人的时候,这个时候呢,我们就想一个问题啊, 如果说这个任务数啊,我招了十个人,这个时候呢?嗯,上面只给十个名额,对不对?这个时候呢,我这个任务数了,已经超出了这个正式员工数,比如说我十个人现在都在干活,你又来了一个任务,我已经没有人可以去执行了啊, 没有人可以去执行的,那么这个时候怎么办呢?那么这个时候在我们企业里面呢,往往不是说再去招人,因为这个时候啊,上面只给你十个名额了,你还要去招这招第十一个人的话,你可能还要去申请,对不对?要去申请这第十一个编制啊,要招要先要把这个编制申请下来,可能呢还要走流程啊,然后这个正式工呢?可能会, 然后这个啊, 就是这个正式工啊,他的这个,呃,招聘的这个流程呢,可能还相当之慢,对不对?那么这个时候怎么办呢?他的就不是说,嗯直接去招人,而且呢你这个时候啊, 那个任务了,可能呢还可以稍微积压一下,比如说你这现在不是十个人在做这十个任务吗?那么这个时候,如果你马上就去,你这个时候,如果你马上就去招第十一个人,那么如果说有,有一个人,你刚把刚把人一招进来,你前面那十个人就已经空出来了人,那怎么办呢?对, 对不对?那么这个时候不是又有人就空闲了吗?那么这个时候呢,就可以了,把这个任务了积压一下,积压一下啊,然后呢先放到堆里里面去,等着这四个十个正式工呢,慢慢的干,然后迟早就会干完了吗?对不对?然后慢慢的慢慢的去做嘛。 但是呢,如果说这个时候任务还在继续增加,已经超出了这个正式工的这个加班的一个忍耐极限,对不对?那么也就说十个人呢,加班都干不过来了,那么你这个任务还在增加怎么办?也就说已经达到这十个人的极限了,那么这个时候呢,可能就要招外包了, 就是我们的,比如说我们的临时工,对吧?因为为什么要招外包而不去招正式工了?我们刚刚讲了,因为招正式工的代价比较大,对吧?然后呢可能上面只给十个名额啊,那么这个时候呢,我可能就要去招一些临时工来, 那么因为招临时工呢,速度比较快,对吧?流程呢也比较快啊,然后呢,可能呢成本也比较低啊,那么这个时候呢,可能我就招一些临时工,而且呢这里还有一个问题,可能这个任务呢,只是 暂时的积压,对不对?而不是说呃,长,这不是一个常态,对不对?这并不是一个常态,那么这个时候呢,我可能就了就招一些临时工,先把这个任务处理完了再说啊,把这个处处任务处理完了,那么这个时候呢 啊,如果说,那么如果说我临时工呢,也已经招了很多了啊,临时工也招了很多了,然后呢我正式工加这个临时工了,还是不能完成任务,就是说这个任务实在太多了,那么这个时候呢,就需要去拒绝了,就是我们的这个县城城的县城池的一个拒绝策略啊。那么所以从这个例子我们呢也能够看出来, 在我们县城池中,我们的县城池考虑的是什么呢?他最最考虑的其实就是这个县城的一个创建啊,就是我们这个县城的创建以及销毁了,他是可靠性能的。那么如果说我,我是核心县城市五个,那么我 每来一个任务,每来一个任务,来第六个任务,来第七个任务,我都去创建县城,然后呢把这第六个任务,第七个任务处理完,那么我这两个县城呢,可能面临着又要被回收掉,对不对?那么呢就会频繁的去创建县城,以及了销毁县城, 那么这个呢不是我们县城池的初衷,县城池的初衷就是为了避免频繁的创建以及的销毁县城啊,所以说呢,先把它添加到队列里面, 添加到对列里边的,这个代价比较小啊,不像我们要频繁的去创建销毁对列,而且呢我们往往使用现成词呢,往往是应对这个,我们这个这个最大现成数啊,我们这个最现成词中的这个最大现成数往往为的就是应对我们的这个 业务的一个峰值,对不对?就是我们的业务的这个繁忙期啊,繁忙期,那么这个时候才是我们这个最大县城存在的一个意义啊,这也就是说 他为什么要先添加队列?为的就是,嗯,不去平凡的创建这个最大县城,那么平凡创建平凡回收啊。啊? 那么这个呢?就是我们这个县城池在这个呃县城池中主色对列是什么作用?以及了啊?后面这个问题啊,为什么要先添加队列而不是呢?先创建最大县城数的一个啊?回答啊。

如何给现成池来命名的?初始画现成池的时候需要显示的命名哎,也就是呃,设置现成池的名称前缀,有利于定位问题。默认情况下创建的现成名字啊,类似于这样的,这样呢,他是没有义务含义的,不利于我们定位问题 啊。给县城池,县城命名通常有两种方式啊,第一种就是使用瓜娃的 three factory builder 啊, 使用它啊,设置现成名称的前缀啊,可以设置为它,然后呃得到一个现成的工厂 啊,给它放入到这个 three 的 pro is cute 这个构造器里面的这个参数里面,可以创建呃自定义名称的现场啊。第二种方式也可以自己实现 three 的 battery 啊, 实现 three 的 factory 啊,重写这个 newsery 方法啊,其中得到现成之后,可以给现成设置名称,自定义现成工厂这种方式也可以设置现成的名称。

现成制主要用在哪啊?现成制主要用在哪?很多的朋友,呃,很多的朋友,呃,喜欢在简历里面写到这个现成尺,写到这个现成尺,那比如说现成制如何实现的呢?其实跟大家讲一下现成尺用的途径啊, 用的场景,好,举个非常简单的例子啊,大家比如说斯文,比如我们作为一个斯文,好, n 个客户端连接,这是客户端一,客户端二,客户端三,客户端四,好, 好克令 a, 克令 b, 好,这边克令的 c 啊,好,这样连 接到服务器上面,连接到服务器上面,服务器端监听在某一个端口上面,连接完以后呢,然后每一个客户端, 每一个服服务器会为每一个呢分配一个对应的连接,这个就是刷客的,就是刷客的啊,对应的 sa 啊,这样,然后呢对应下 sb, 然后每一个对应上,好,这里我们就出现一个现象,好,先把画面笔打开一下, 好,大家每位朋友呢?好,这里连接到也就是这个客户,他 a 发数据啊, 服务端这边 read 或者 receive, 两个都是可以的,去读这个 fd, 读这个 socky 的,我们就可以读出他的数据出来。然后客户端 b 呢,同样在服务器上面 也有一个对应的连接,那各位这个类似的 fd 呢?类似的 fd 只用于建立连接用,只用于我们建立连接。客户当十一呢,同样也是好客户当第一呢,也是这样的, 也是这样的,所以在这里面 society 就分为两类,一类是类似的 fd, 一类是我们肯定 fd 用来跟客户端之间通信的,这里后面进行 receive 三的是对后面的 fd, 前面这个 fd 呢?这个类似 fd 呢,我们用 ucsf 的进行处理啊,这样大家应该能够听懂啊。 好,那这个线上池在这个里面我们怎么去用呢?如何去用?其实这里面关于线上池我们有这么几个用法,第一个,第一个就是当我们接收完客户端 a 的数据,比如说客户端 a 这边发一个,你好好,这个数据报基于 tcp 呢,可能我们还有一些其他的协议,非常复杂的协议,然后前面加上一段什么,呃,包场有多少,然后对应的这种协议的类型是多少?哇哇一系列的,然后这个 对去读这个 fd 的时候,读完之后第一种方式就是把这个数据放到我们进行解析。好,客户端 发送的数据解析啊,这是第一个作用,第一个用的场景用的时候解析完,对啊,我们把这数据读出来以后,把对应的 boss 放到线上池,由线上池进行解析,解析完比如进行数据库操作,进行对应的缓存操作,进行对应的,比如写到日子里面,都是这里线程池用作业务 解析,这是第一种做法。第一种做法,这种做法上面呢也是比较常见的,大家你就会发现这里面限制词主要是用来做数据解析,除了之外还有没有呢?除了这个场景之外,我们同样还可以。 这个用法呢,可能会有点问题,但是也有这么用的,就是每一次我们俄克赛不等 好,对于连接比较少的时候,分配完之后,当有新的连接都有,当有新的数据一块检测这些 i o 有数据的时候,再把这个 io f d 丢给现身池,这里面请注意现身池处理 fd 好。大家可能说我是不是一起都用了,各方不是的,结合自己不一样的问题去解决,很多的朋友, 很多的朋友很有一个问题啊,对技术的理解,他有一个问题啊,就是很容易把这种去堆技术,去堆技术,技术 他核心是用来解决问题的一个手段,就是你能够搞定问题,这个东西叫做技术,如果搞不定问题,你引用再多新的技术名词引入进去,他也不叫技术,他使得你这个性能效率会比较的慢。 好,这跟大家讲的讲回来,现成持核心的作用,在这里提到的他进行业务的处理,数据的处理。

县城池如何知道一个县城的任务已经执行完成?一、在县城池内部,当我们把一个任务丢给县城池去执行,县城池会调度工作县城来执行这个任务的 ram 方法。 ram 方法正常结束,也就意味着任务完成了。 所以县城池中的工作县城是通过同步调用任务的 ran 方法,并且等待 ran 方法返回后再去统计任务的完成数量。二、如果想在县城池外部去获得县城池内部任务的执行状态, 有几种方法可以实现?二、线乘持提供了一个 exterminated 方法,可以判断线乘持的运行状态。我们可以循环判断 exterminated 方法的反 返回结果来了解县城池的运行状态。一旦县城池的运行状态是 terminated, 意味着县城池中的所有任务都已经执行完了。想要通过这个方法 获取状态的前提是程序中主动调用了县城池的 shutdom 方法。在实际业务中一般不会主动去关闭县城池, 因此这个方法在实用性和灵活性方面都不是很好。 b、 在县城池中有一个 sup meet 方法,它提供了一个 future 的返回值,我们通过 future get 方法来获得任务的执行结果。 当线城池中的任务没执行完之前, future get 方法会一直阻塞,直到任务执行结束。因此,只要 到 future get 方法正常返回,也就意味着传入到县城池中的任务已经执行完成了。 c、 可以引入一个 countdown latch 计数器,它可以通过初始化指定一个计数器进行倒计时。 其中有两个方法,分别是 awake 阻塞线程以及 countdown 进行倒计时,一旦倒计时归零,所以被阻塞在 await 方法的线程都会被释放。基于这样的原理,我们可以定义一个 countdown latch 对象,并且计数器为一, 接着在县城池代码块后面调用 await 方法组色主县城,然后当传入到县城池中的任务执行完成后,调用 countdown 方法 表示任务执行结束,最后计数器归零,零唤醒阻塞在 outweight 方法的线程。三基于这个问题,我简单总结一下,不管是线程尺内部还是外部,要想知道线程是否执行结束,我们必须要获取线程 执行结束后的状态,而县城本身没有返回值,所以只能通过阻塞缸唤醒的方式来实现。 future get 和 countdown latch 都是这样一个原理。

今天威哥给大家解析一道源自阿里阴面的面试题,说说县城池的参数设置。接下来我们就开始解析这道面试题。我们都知道县城池有两个非常重要的参数,核心县城数和最大县城数,那这两个参数该如何设置呢? 我们对县城值负责执行的任务分为两种情况,一种是 cpu 密进行任务,一种是 io 密进行任务。 cpu 密进行任务,也叫计算密进行任务,比如加密、解密、 压缩计算等一系列需要大量消耗 cpu 资源的任务。 io me 进行任务,比如数据库文件 io 的读写、网络的通信等任务。 接下来我们看一下 cpu 密集性任务。 cpu 密集性任务的特点是县城在执行任务时会一直利用 cpu, 所以对于这种情况,应当尽可能的避免发生县城的上下文切换,比如单核 cpu 环境,假如两个县城 a 和 b 同时 执行任务 c 和 d 因为存在上下文切换,所以完成任务需要的总时间是任务 c 执行的时间加上任务 d 执行的时间加上县城上下文切换的时间。而如果只有一个县城来执行这两个任务,因为不存在上下文的切换,所以执行时间是任务 c 的执行时间加上任务 d 的执行时间。所以对于 cpu mi 进行任务, 线程数最好等于 cpu 核心数。但是考虑的意外情况,对于 cpu 密集性任务,我们建议线程数设置成 cpu 核心数加一 iome 进行任务。线程在执行 iome 进行任务时,可能大部分时间都阻塞在 io 上。 假如现在有十个 cpu, 如果我们只设置了十个线程来执行 iome 进行任务,那么很有可能这十个线程都阻塞在 io 上,所以对于 io 型任务,我们通常会设置成线程数为二乘以 cpu 的核心数。不过就算设置成了二乘以 cpu 的核心数也不 一定是最佳的。因为有十个 cpu 线程数为二十,那么就有可能这二十个线程同时组织在 io 上,所以可能再增加线程,从而去加大 cpu 的利用率。通常我们会通过以下的公式来进行计算,这也是加法并发编程实战的作者推荐的算法。线程数等于 cpu 的含义数乘以 加上县城等待时间,除以县城运行总时间,我们可以利用且尾数 v m 除样来估计这两个时间。如果想要得到更准确的县城数,可以进行压测, 监测 gvm 的现成情况以及 cpu 的负载情况,根据实际情况衡量应该创建的现成数,合理并充分的利用资源。接下来我们做一下总结。 cpu 密进行任务 建议 cpu 核心数加一 iome 进行任务建议先通过公式算出一个理论值,再通过压测算出最优值。对于核心任务,可以把线乘数设置成我们压测出来的结果,最大线乘数可以等于核心线乘 数或者大一点。比如我们压测时可能会发现五百个线程最佳,但是六百个线程时也还行,其实六百就可以认为是最大线程数。对于非核心任务, 线程数设置的可以比较小,避免操作系统去维护不必要的线程。最大线程数可以设置为我们计算或者压测出来的结果。小伙伴们,关注威哥,更多精品内容持续与你分享!