java 动态线程池_线程池的参数动态调整

2023-10-27

经典面试题

这次的文章还是绕回了我写的第三篇原创文章《有的线程它死了,于是它变成一道面试题》中留下的几个问题:

8b97fddc7ffec14f66ab3d5ae19ef733.png

哎,兜兜转转,走走停停。天道好轮回,苍天饶过谁?

edb3485c40d6da9329279d7c81a082b3.png

在这篇文章中我主要回答上面抛出的这个问题:你这几个参数的值怎么来的呀?

要回答这个问题,我们得先说说这几个参数是什么,请看截图:

343f100583371dade066aa7e3e1ae89a.png

其实,官方的注释写的都非常明白了。你看文章的时一定要结合英文,因为英文是 Doug Lea(作者)他自己写的,表达的是作者自己的准确的想法。

不要瞎猜好吗?

27598d9462af172cb10577841b263096.png

1.corePoolSize:the number of threads to keep in the pool, even if they are idle, unless {@code allowCoreThreadTimeOut} is set

(核心线程数大小:不管它们创建以后是不是空闲的。线程池需要保持 corePoolSize 数量的线程,除非设置了 allowCoreThreadTimeOut。)

2.maximumPoolSize:the maximum number of threads to allow in the pool。

(最大线程数:线程池中最多允许创建 maximumPoolSize 个线程。)

3.keepAliveTime:when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating。

(存活时间:如果经过 keepAliveTime 时间后,超过核心线程数的线程还没有接受到新的任务,那就回收。)

4.unit:the time unit for the {@code keepAliveTime} argument

(keepAliveTime 的时间单位。)

5.workQueue:the queue to use for holding tasks before they are executed. This queue will hold only the {@code Runnable} tasks submitted by the {@code execute} method。

(存放待执行任务的队列:当提交的任务数超过核心线程数大小后,再提交的任务就存放在这里。它仅仅用来存放被 execute 方法提交的 Runnable 任务。所以这里就不要翻译为工作队列了,好吗?不要自己给自己挖坑。)

6.threadFactory:the factory to use when the executor creates a new thread。

(线程工程:用来创建线程工厂。比如这里面可以自定义线程名称,当进行虚拟机栈分析时,看着名字就知道这个线程是哪里来的,不会懵逼。)

7.handler :the handler to use when execution is blocked because the thread bounds and queue capacities are reached。

(拒绝策略:当队列里面放满了任务、最大线程数的线程都在工作时,这时继续提交的任务线程池就处理不了,应该执行怎么样的拒绝策略。)

7 个参数介绍完了,我希望当面试官问你自定义线程池可以指定哪些参数的时候,你能回答的上来。

当然,不能死记硬背,这样回答起来磕磕绊绊的,像是在背书。也最好别给我回答什么:我给你举个例子吧,就是一开始有多少多少工人....

2a9293fca863474dbb729c6492633b2a.gif

没必要,真的,直接回答每个参数的名称和含义就行了,牛逼的话你就给我说英文也行,我也能听懂。

这玩意大家都懂,又不抽象,你举那例子干啥?拖延时间吗?

面试要求的是尽量精简、准确的回答问题,不要让面试官去你冗长的回答中提炼关键字。

一是面试官面试体验不好。面试完了后,常常是面试者在强调自己的面试体验。朋友,你多虑了,你面试体验不好,回去一顿吐槽,叫你进入下一轮面试的时候,大部分人还不是腆着个脸就来了。面试官的体验不好,那你是真的没有下一轮了。

二是面试官面试都是有一定的时间限制的,有限的面试时间内,前面太啰嗦了,能问你的问题就少了。问的问题少了,面试官写评分表的时候一想,我靠,还有好多问题没问呢,也不知道这小子能不能回答上来,算了,就不进入下一轮了吧。

好了好了,一不下心又暴露了几个面试小技巧,扯远了,说回来。

db13792b013b5f22f538e232537346bc.png

上面的 7 个参数中,我们主要需要关心的参数是: corePoolSize、maximumPoolSize、workQueue(队列长度)。

所以,文本主要讨论这个问题:

当我们自定义线程池的时候 corePoolSize、maximumPoolSize、workQueue(队列长度)该如何设置?

你以为我要给你讲分 IO 密集型任务或者分 CPU 密集型任务?

不会的,说好的是让面试官眼前一亮、虎躯一震、直呼牛皮的答案。不骗你。

327cca2bd657b859a5375fcdf5dd22eb.gif

美团骚操作

怎么虎躯一震的呢?

第一次看到这篇文章的时候我真是眼前一亮,看到美团的这骚操作,我真是直呼牛皮。

(哎,还是自己见的太少了。)

这篇文章写的很好,很全面,比如我之前说的线程执行流程,它配了一张图,一图胜千言:

21e250ee37e0ae85f790a8d8572d201e.png

阻塞队列成员表,一览无余:

b83c0d3bc5ef316b0b09b4cb7d7b37a7.png

前面都是些基础知识,文中的后半部分才抛出了一个实际问题:

线程池使用面临的核心的问题在于:线程池的参数并不好配置。

一方面线程池的运行机制不是很好理解,配置合理需要强依赖开发人员的个人经验和知识;

另一方面,线程池执行的情况和任务类型相关性较大,IO密集型和CPU密集型的任务运行起来的情况差异非常大。

这导致业界并没有一些成熟的经验策略帮助开发人员参考。

美团给出的对应的解决方案是什么呢?

线程池参数动态化。

尽管经过谨慎的评估,仍然不能够保证一次计算出来合适的参数,那么我们是否可以将修改线程池参数的成本降下来,这样至少可以发生故障的时候可以快速调整从而缩短故障恢复的时间呢?

基于这个思考,我们是否可以将线程池的参数从代码中迁移到分布式配置中心上,实现线程池参数可动态配置和即时生效,线程池参数动态化前后的参数修改流程对比如下:

4246049cb9d477625393bd882f12d411.png

说实话看到这个图的时候我想起之前也有这样的想法的。

因为有一次我这边有个项目里面的定时任务用到了线程池,但是核心线程数和队列长度都设置的比较大,某一次任务触发后查出了大批数据,通过线程池提交任务,每个任务里面都会调用下游服务,导致下游服务长时间的压力过大,也没有做限流,所以影响了其对外提供的其他功能。

于是我叫运维帮我在 Apollo(配置中心)调小了核心线程数,并且重启了服务。

那一次我就在想,我们使用的是 Apollo 天然支持动态更新,那我能不能动态的修改线程池呢?

因为那个时候不知道一个构建好了的线程池,它的核心线程数和最大线程数是可以动态修改的。

aa2cd1a932f6b78444e7693c030dc8a0.png

所以最开始的想法是监听到参数变化后,直接弄一个新的线程池把原来的给替换掉。

但这样的问题是,偷天换日之后,原来的线程池里面的任务我怎么处理呢?

我不能等原来的线程池里面的任务执行完成后再换,因为这个时候任务一定是源源不断的过来的。

于是就卡在了这个地方。

说来惭愧,这块源码我看过几次,但还是差点火候,学艺不精,怨不得别人。

be3aaa8799517a1e429b20818ad4ba80.png

先劝退一波

为了不浪费你的时间,先检测一下你是否有阅读本文的基础知识储备:

首先,我们先自定义一个线程池:

2661d544de1dc81de06c5fad31ff439d.png

拿着这个线程池,当这个线程池在正常工作的前提下,我先问你两个问题:

1.如果这个线程池接受到了 30 个比较耗时的任务,这个时候线程池的状态(或者说数据)是怎样的?

2.在前面 30 个比较耗时的任务还没执行完成的情况下,再来多少个任务会触发拒绝策略?

其实这就是在问你线程池的执行流程了,简单的说一下就是:

1.当接收到了 30 个比较耗时的任务时,10 个核心线程数都在工作,剩下的 20 个去队列里面排队。这个时候和最大线程数是没有关系的,所以和线程存活时间也就没有关系。

2.其实你知道这个线程池最多能接受多少任务,你就知道这个题的答案是什么了,上面的线程池中最多接受 1000(队列长度) + 30(最大线程数) = 1030 个任务。所以当已经接收了30个任务的情况下,如果再来 1000 个比较耗时的任务,这个时候队列也满了,最大线程数的线程也都在工作,这个时候线程池满载了。因此,在前面 30 个比较耗时的任务还没执行完成的情况下,再来 1001 个任务,第 1001 个任务就会触发线程池的拒绝策略了。

这两个问题你得会,如果答不上来你也别往下看了,大概率看的一脸懵逼。

我建议你先给本文点个赞,接着去网上搜一下线程池执行流程的文章(其实美团的那篇文章也写了执行流程),写个 Demo 跑一下,摸清楚了,再来看这篇文章。

8f235085005aac233ae71be06350eb07.gif

巨人肩膀

对于线程池参数到底如何设置的问题美团的那篇文章提供了一个很好的思路和解决方案,展现的是一个大而全的东西。

但是,对于实施起来的细节就没有具体的展示了。

所以文本斗胆,站在巨人的肩膀上对细节处进行一些补充说明。

1.现有的解决方案的痛点。

2.动态更新的工作原理是什么?

3.动态设置的注意点有哪些?

4.如何动态指定队列长度?

5.这个过程中涉及到的面试题有哪些?

下面从这五点进行展开说明。

3968cc327409c5efde8f929802c46a66.png

现有的解决方案的痛点。

现在市面上大多数的答案都是先区分线程池中的任务是 IO 密集型还是 CPU 密集型。

如果是 CPU 密集型的,可以把核心线程数设置为核心数+1。

为什么要加一呢?

《Java并发编程实战》一书中给出的原因是:即使当计算(CPU)密集型的线程偶尔由于页缺失故障或者其他原因而暂停时,这个“额外”的线程也能确保 CPU 的时钟周期不会被浪费。

看不懂是不是?没关系我也看不懂。反正把它理解为一个备份的线程就行了。

这个地方还有个需要注意的小点就是,如果你的服务器上部署的不止一个应用,你就得考虑其他的应用的线程池配置情况。

经过精密的计算,你咔一下设置为核心数,结果项目部署上去了,发现还有其他的应用在和你抢 CPU,你想想难不难受。

003a84460cad6a83d27f4e2280886981.png

如果是包含 IO 操作的任务呢?这个才是我们关心的东西。

《Java并发编程实战》一书中给出的计算方式是这样的:

42b48ce357fc721ca98353d99146e4a1.png

理想很丰满,现实很骨感。

我之前有个系统就是按照这个公式算出来的参数去配置的。

结果效果并不好,甚至让下游系统直呼受不了。

这个东西怎么说呢,还是得记住,面试的时候有用。真实场景中只能得到一个参考值,基于这个参考值,再去进行调整。

我们再看一下美团的那篇文章调研的现有解决方案列表:

6b86e4764d10ebde171bcb58665b8286.png

第一个就是我们上面说的,和实际业务场景有所偏离。

第二个设置为 2*CPU 核心数,有点像是把任务都当做 IO 密集型去处理了。而且一个项目里面一般来说不止一个自定义线程池吧?比如有专门处理数据上送的线程池,有专门处理查询请求的线程池,这样去做一个简单的线程隔离。但是如果都用这样的参数配置的话,显然是不合理的。

第三个不说了,理想状态。流量是不可能这么均衡的,就拿美团来说,下午3,4点的流量,能和 12 点左右午饭时的流量比吗?

基于上面的这些解决方案的痛点,美团给出了动态化配置的解决方案。

a9f063e8c3e8f59890bfe9b900afd04b.png

动态更新的工作原理是什么?

先来一个动态更新的代码示例:

f0e45c52f02df929ec937954ebb280de.png

上面的程序就是自定义了一个核心线程数为 2,最大线程数为 5,队列长度为 10 的线程池。

然后给它塞 15 个耗时 10 秒的任务,直接让它 5 个最大线程都在工作,队列长度 10 个都塞满。

当前的情况下,队列里面的 10 个,前 5 个在 10 秒后会被执行,后 5 个在 20 秒后会被执行。

再加上最大线程数正在执行的 5 个,15 个任务全部执行完全需要 3 个 10 秒即 30 秒的时间。

这个时候,如果我们把核心线程数和最大线程数都修改为 10。

那么 10 个任务会直接被 10 个最大线程数接管,10 秒就会被处理完成。

剩下的 5 个任务会在 10 秒后被执行完成。

所以,15 个任务执行完成需要 2 个 10 秒即 20 秒的时间处理完成了。

看一下上面程序的打印日志:

91feee35e44c4db621ac79ea76d617d2.png

效果实现了,我先看一下原理是什么。

先看 setCorePoolSize 方法:

b952cb4f605c579a5d5521421be85e1b.png

这个方法在美团的文章中也说明了:

在运行期线程池使用方调用此方法设置corePoolSize之后,线程池会直接覆盖原来的corePoolSize值,并且基于当前值和原始值的比较结果采取不同的处理策略。

对于当前值小于当前工作线程数的情况,说明有多余的worker线程,此时会向当前idle的worker线程发起中断请求以实现回收,多余的worker在下次idel的时候也会被回收;

对于当前值大于原始值且当前队列中有待执行任务,则线程池会创建新的worker线程来执行队列任务,setCorePoolSize具体流程如下:

c64b2fd00514d42d24ba38bf274a5223.png

看了美团的那篇文章后,我又去看了 Spring 的 ThreadPoolTaskExecutor类 (就是对JDK ThreadPoolExecutor 的一层包装,可以理解为装饰者模式)的 setCorePoolSize 方法: 注释上写的清清楚楚,可以在线程池运行时修改该参数。

95053bb323a1a4a2984820a6642cc372.png

而且,你再品一品 JDK 的源码,其实源码也体现出了有修改的含义的,两个值去做差值,只是第一次设置的时候原来的值为 0 而已。

哎,当时没有细细研究,恨自己看源码的时候不仔细。

7da2baabd5dbddebea2f039c321d430f.png

3fec0228df344efbd22f5cc2d25759d3.png

接着看 setMaximumPoolSize 源码:

85c39118768b6db8bfafc8169893a520.png

这个地方就很简单了,逻辑不太复杂。

1.首先是参数合法性校验。

2.然后用传递进来的值,覆盖原来的值。

3.判断工作线程是否是大于最大线程数,如果大于,则对空闲线程发起中断请求。

经过前面两个方法的分析,我们知道了最大线程数和核心线程数可以动态调整。

动态设置的注意点有哪些?

调整的时候可能会出现核心线程数调整之后无效的情况,比如下面这种:

0316e3f3f0090fe78f6b0d34821ce711.png

改变之前的核心线程数是 2,最大线程数为 5,我们动态修改核心线程数为 10。

但是从日志还是可以看出,修改之后核心线程数确实变成了 10,但活跃线程数还是为 5。

而且我调用了 prestartCoreThread 方法,该方法见名知意,你也知道是启动所有的核心线程数,所有不存在线程没有创建的问题。

这是为什么呢?

源码之下无秘密,我带你去看一眼:

java.util.concurrent.ThreadPoolExecutor#getTask

5e6e930b9b771e99eebe32f322ee1c51.png

在这个方法中我们可以看到,如果工作线程数大于最大线程数,则对工作线程数量进行减一操作,然后返回 null。

所以,这个地方的实际流程应该是: 创建新的工作线程 worker,然后工作线程数进行加一操作。 运行创建的工作线程 worker,开始获取任务 task。 工作线程数量大于最大线程数,对工作线程数进行减一操作。 返回 null,即没有获取到 task。 清理该任务,流程结束。

这样一加一减,所以真正在执行任务的工作线程数的数量一直没有发生变化,也就是最大线程数。

怎么解决这个问题呢?

答案已经呼之欲出啦。

设置核心线程数的时候,同时设置最大线程数即可。其实可以把二者设置为相同的值:

83e345c55f492978445725fa6179c6a8.png

这样,活动线程数就能正常提高了。

f0e0dfce7b2a299a9c16230036608b08.png

有的小伙伴就会问了:如果调整之后把活动线程数设置的值太大了,岂不是业务低峰期我们还需要人工把值调的小一点?

不存在的,还记得前面介绍 corePoolSize 参数的含义时的注解吗:

ee66b49fbcb1bf8664c7dafac74fde03.png

当 allowCoreThreadTimeOut 参数设置为 true 的时候,核心线程在空闲了 keepAliveTime 的时间后也会被回收的,相当于线程池自动给你动态修改了。

如何动态指定队列长度?

前面介绍了最大线程数和核心线程数的动态设置,但是你发现了吗,并没有设置队列长度的 set 方法啊?

6d7a443c42d2963639ae68f2ffcef228.png

有的小机灵鬼说先获取 Queue 对象出来再看一下呢?

f5596eb386c5c387157245c76d0f73e7.png

还是没有,这可咋整呢?

首先我们看一下为什么没有提供队列长度的 set 方法呢:

因为队列的 capacity 是被 final 修饰了呀。

eb6494e40c5e9d05f47873e53c325c74.png

但是美团的那篇文章明明说了,他们也支持队列的动态调整呀:

276728e310c863622531f4b47530143f.png

可是没有详细说明,但是别着急,接着看后面的内容可以发现他们有一个名字为 ResizableCapacityLinkedBlockIngQueue 的队列:

ae5e65e34bd01fcfd711adc4faf429cb.png

很明显,这是一个自定义队列了。

我们也可以按照这个思路自定义一个队列,让其可以对 Capacity 参数进行修改即可。

操作起来也非常方便,把 LinkedBlockingQueue 粘贴一份出来,修改个名字,然后把 Capacity 参数的 final 修饰符去掉,并提供其对应的 get/set 方法。

34a1611dfde3da184fa0fa8a61018e1e.png

然后在程序里面把原来的队列换掉:

865efefd23a70a0d8b5e572333405fe0.png

运行起来看看效果:

adb9a087fdf483b5549b398147c0679c.png

可以看到,队列大小确实从 10 变成了 100,队列使用度从 100% 降到了 9%。

我后来去看了美团的那篇文章下面的评论,有个评论是这样的:

971038409d8b76c1767f9c298f70a708.png

果然不出我所料。

f46eb9053df477675d534dd627836a7d.png

这个过程中涉及到的面试题有哪些?

问题一:线程池被创建后里面有线程吗?如果没有的话,你知道有什么方法对线程池进行预热吗?

线程池被创建后如果没有任务过来,里面是不会有线程的。如果需要预热的话可以调用下面的两个方法:

全部启动:

bec77cc3659ddf721ada6c81c6094d71.png

仅启动一个:

2901913e251c2f3be5497297a19b6fab.png

问题二:核心线程数会被回收吗?需要什么设置?

核心线程数默认是不会被回收的,如果需要回收核心线程数,需要调用下面的方法:

1a79935a1f9bd95a71d9dab35de4d5f4.png

allowCoreThreadTimeOut 该值默认为 false。

7588290ae07f96f938cebf506005c81f.png

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java 动态线程池_线程池的参数动态调整 的相关文章

  • Postern + Charles + Burpsuite 进行对 APP 进行抓包

    Postern Charles Burpsuite 进行对 APP 进行抓包 一 简单介绍 二 配置环境 三 配置 Charles 四 配置 postern 五 配置 Charles Burpsuite 六 Charles 和 Fiddle
  • STM32与ST-LINK/V2报错的解决方法

    追加阅读 STM32与ST LINK V2报错的解决方法 2 今天到入手了一块STM32F103C8T6最小系统版 想烧录点程序进去 发现keil5软件偶尔能检测到板子 大多数时候会报一堆错误 串口更是找不到 遇见的问题包括但不限于 ST
  • 【Qt】利用Tool Button控件创建下拉菜单按钮

    功能描述 利用qt进行界面设计和开发 创建下拉按钮 详细实现 1 在qt侧工具栏利用设计打开 ui文件 2 创建按钮 创建一个Tool Button按钮 并在属性窗口中的QToolButton栏中选中MenuButtonPopup属性 3
  • [从零开始学DeepFaceLab-3]: 使用-开发环境准备

    目录 1 GPU环境 1 1 安装N卡驱动程序 2 Python环境 2 1 安装Anaconda 2 2 安装tensorflow 2 3 GPU库的安装
  • linux用less查看文件内容,Linux文件内容查看 - less命令

    查看nohup out文件的内容 大于10万行 显示行号 显法读取文件的百分比 行号及总行数 root li384 34 data grainger images less NM nohup out 1 Searching for imag
  • MyBatis插入时获取自增id

    关于MyBatis在插入时获取自增id 1 1 注释方法 Insert insert into book bid bname price number cratedate values null bname price number cra
  • Netty网络编程(三):Channel详解

    文章目录 简介 Channel详解 异步IO和ChannelFuture Channel的层级结构 释放资源 事件处理 总结 简介 Channel是连接ByteBuf和Event的桥梁 netty中的Channel提供了统一的API 通过这
  • SpringBoot -ElasticSearch RestHighLevelClient 高级客户端使用(1) 初始化

    此处使用ElasticSearch6 4 2版本 SpringBoot 和ElasticSearch 环境以及 安装ik分词等操作不再缀诉 直接进入整合 本节不阐述原理 导入依赖 此处使用的elasticsearch为6 4 2版本 Spr
  • mdk5.14无法烧录

    mdk无法烧录 报错信息 Full Chip Erase Done No Algorithm found for 08000000H 080019E7H Programming skipped Error Flash Download fa
  • 应用接口版本兼容设计和使用原则

    背景 由于不同版本的升级与APP的客户端的升级是一致的 所以接口就不能像web一样能实时更新 代码可以每次拉取都不同 因为接口更新就应该遵守连续性原则 几个版本解释 在项目开发过程中 为了不同的目的 我们会出现很多版本管控 对于新人来说 有
  • 关于两个不同的List,根据相同属性进行排序

    两个不同的List 根据相同的属性进行排序 直接上代码 这里比较的是相同的list 有不同的可以直接放进去就行了 import java util public class Test public static void main Stri
  • 在Java中使用网络框架编写网络应用程序

    前言 自从JDK1 4中有了NIO以后 这个方面越来越活跃 也为java赢得更多开发者的支持 做java网络编程需要掌握一些基本的知识和技能 套接字编程 阻塞 非阻塞通信 创建HTTP服务器与客户程序 数据报通信 对象的序列化与反序列化 J
  • 【Python数列、数列和问题】

    1 e的计算可用如下表达式展开 试计算e 精确到小数点后6位小数 代码 s 0 item 1 jc 1 n 0 while abs item gt 1e 6 s s item n n 1 jc jc n item 1 jc print 6f
  • 生活之手机控制电脑

    在宿舍的可以候睡觉的时候可以看电脑里面的东西就好了 使用teamviewer就可以 用teamviewer还可以进行远程控制 感觉还是挺好玩的 http android d cn news 1640 html
  • ajax异步加载解析复杂json(集合中包含对象,对象中包含对象)数据

    1 例如后台返回的json数据如下 id 1 name 2 user name 2 age 18 id 2 name 2 user name 2 age 18 2 前台解析代码如下 var obj eval s 进行格式的转化 然后就能采用
  • bat添加到windows服务

    1 编写bat脚本 注释 echo off 显示当前日期时间 echo data time 切换到指定的VUE服务器工作路径 cd d e ColleagueFiles pvGrid nanRui demo 执行vue服务启动命令 前提条件
  • java.net.SocketTimeoutException: connect timed out

    1 禁用Linux防火墙 未解决 2 禁用Windows防火墙 未解决 3 Linux ping Windows ip ping 不通 4 关闭windows防火墙 未解决 5 重启电脑 未解决 6 关闭迈克菲防火墙 问题解决
  • 邮件系统收发邮件报错汇总——错误代码550

    550报错是收发邮件时常见的报错 今天我们就一起来盘点一下关于MDaemon邮件服务器550报错的原因 以及如何解决 有所不周之处 还望网友提醒 第一种 退信 550 connection refused 报错截图如下 原因 这个是因为ip
  • 凸集的开、闭、紧

    凸集的开 闭 紧 更新于20181220 01 13之前的定义有疏漏 特别是对开凸集的定义是错误的臆想 举出的一个例子半开半闭 对于开集 开集 是拓扑学里最基本的概念之一 设A是度量空间X的一个子集 如果A中的每一个点都有一个以该点为球心的

随机推荐

  • 使用python获取当前时间的13位时间戳

    import time import datetime def get timestamp datetime object datetime datetime now now timetuple datetime object timetu
  • java 局部变量作用域_Java基础之:属性与局部变量作用域

    Java基础之 属性与局部变量作用域 简单案例 class A int age 属性 public void print System out println age String name 小范 System out println na
  • Nginx 出现 403 Forbidden 最终解决

    步骤一 检查目录权限 权限不足的就加个权限吧 例子 chmod R 755 var www 步骤二 打开nginx conf 例子 vim etc nginx nginx conf 把 user 用户名 改为 user root 或 其它有
  • 验证回文串

    给定一个字符串 验证它是否是回文串 只考虑字母和数字字符 可以忽略字母的大小写 说明 本题中 我们将空字符串定义为有效的回文串 示例 1 输入 A man a plan a canal Panama 输出 true 解释 amanaplan
  • 蜜罐技术

    蜜罐技术 就是设置一个假的服务器 用来诱使攻击者进行攻击 一般来说 攻击者想对用户进行攻击时 会先进行扫描行为 以便发现用户的服务器以及对应的漏洞 这样就可以进行针对性的攻击 蜜罐技术 可以设置一个满是漏洞的假服务器 这样很容易被攻击者所发
  • vite创建vue2项目

    使用vite首先需要注意官方给出的兼容性注意 Vite 需要 Node js 版本 14 18 16 然而 有些模板需要依赖更高的 Node 版本才能正常运行 当你的包管理器发出警告时 请注意升级你的 Node 版本 1 初始化vite项目
  • 英文单词发音规则

    本文链接 http www php oa com 2008 01 31 yingyudancifayinguize html 英语单词发音规则开闭音节的概念 开音节1 以发音的元音字母结尾的单节 例 be he 2 以辅音字母 r 除外 不
  • matlab生成随机信号序列_信号处理工具箱:基本信号发生器

    信号是现代工程中经常处理的对象 在通信 雷达等领域有大量的应用 在MATLAB中 信号处理工具箱可以看做工具集合 包含波形产生与处理 数字和模拟滤波器设计 信号模型以及频谱分析 时频分析等多个常见功能 在MATLAB信号工具箱中 提供了多种
  • H2 (一个开源的关系数据库)

    Welcome to H2 the Java SQL database The main features of H2 are Very fast open source JDBC API 快速 开源 Embedded and server
  • 元宇宙基本概念、特点及发展趋势初步探讨

    摘要 当前元宇宙 Metaverse 的概念逐渐深入人心 成为近期区块链 人工智能行业热议的重点 本文将从元宇宙的基本概念 元宇宙产生以及元宇宙未来发展等方面 深度分析元宇宙及其发展趋势 一 概述 近一段时间以来 在互联网投资圈和资本圈里
  • Java中的适配器模式(Adapter Pattern)

    Java中的适配器模式 Adapter Pattern 简介 适配器模式 Adapter Pattern 是一种常用的设计模式 用于将一个类的接口转换成客户端所期望的另一个接口 在Java中 适配器模式可以帮助我们解决不兼容接口之间的问题
  • opencv:用最邻近插值和双线性插值法实现上采样(放大图像)与下采样(缩小图像)

    上采样与下采样 概念 上采样 放大图像 或称为上采样 upsampling 或图像插值 interpolating 的主要目的 是放大原图像 从而可以显示在更高分辨率的显示设备上 下采样 缩小图像 或称为下采样 subsampled 或降采
  • 【区间DP题解】 关路灯

    Link 题目 题目描述 某一村庄在一条路线上安装了 n 盏路灯 每盏灯的功率有大有小 即同一段时间内消耗的电量有多有少 老张就住在这条路中间某一路灯旁 他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯 为了给村里节省电费 老张记录下了
  • A Survey of Large Language Models

    本文是LLM系列的第一篇文章 针对 A Survey of Large Language Models 的翻译 大语言模型综述 摘要 1 引言 2 概述 2 1 LLM的背景 2 2 GPT系列模型 的技术演化 3 LLMs的资源 3 1
  • 新优选商城上线发布会,京庐空间执行总裁赵娅勤女士接受采访!

    新优选商城上线发布会 京庐空间执行总裁赵娅勤女士接受采访现场 互联网的快速发展对于推动各行各业重构商业业态具有深远的历史影响 互联网发展进入21世纪 在全球信息化进程加快的背景下 电子商务 新零售 社交电商等行业业态也为传统行业提供了新的增
  • 正交试验设计例题及答案_正交矩阵求解

    我对题的难度进行划分 满难度是 难度中包含 计算难度和 思路难度 满难度各 难度评测是以我初见题目视角写出的标准 比较主观 另外 考试时的解答时间的长短也需要考虑 毕竟有些东西复习多了见过了 或者看过答案了就不难了 假如每颗 代表20分 我
  • ubuntu:关闭某个进程

    参考 http blog csdn net chen861201 article details 6980677 ps aux grep xxx 程序名称 kill xxx 某个PID
  • ganglia监控hadoop 容器节点

    hadoop容器运行参考上篇博客 http blog csdn net wenwenxiong article details 78973755 参看网址 https gist github com ameizi 0c77e3dbb13de
  • (二十五)admin-boot项目之集成消息队列Rabbitmq

    目录 项目地址 https gitee com springzb admin boot 如果觉得不错 给个 star 简介 这是一个基础的企业级基础后端脚手架项目 主要由springboot为基础搭建 后期整合一些基础插件例如 redis
  • java 动态线程池_线程池的参数动态调整

    经典面试题 这次的文章还是绕回了我写的第三篇原创文章 有的线程它死了 于是它变成一道面试题 中留下的几个问题 哎 兜兜转转 走走停停 天道好轮回 苍天饶过谁 在这篇文章中我主要回答上面抛出的这个问题 你这几个参数的值怎么来的呀 要回答这个问