详细说说 JDK 的线程池的创建参数
文章目录
- 1. 概要
- 2. 线程的核心参数
- 2.1.核心线程和最大线程
- 2.2.任务队列
- 2.2.1.ArrayBlockingQueue
- 2.2.2.LinkedBlockingQueue
- 2.2.3.SynchronousQueue
- 2.2.4.PriorityBlockingQueue
- 2.2.5.DelayQueue
- 2.2.7.LinkedBlockingDeque
- 2.3 keepAliveTime
- 2.4 ThreadFactory
- 2.5 拒绝策略
- 3. JDK 提供的几种默认的线程池实现
- 3.1 newFixedThreadPool
- 3.2 newCachedThreadPool
- 3.3 newSingleThreadExecutor
- 3.4 newScheduledThreadPool
- 4. 为什么不推荐使用上面的线程池
- 5. 小结
1. 概要
线程池(Thread Pool)是一种并发编程的技术,用于管理一组线程,以便复用这些线程来执行多个任务。使用线程池的核心目的就是用来减少线程的创建和销毁的开销,从而能提高系统的响应性能,同时线程池对线程的管理也能避免线程创建过多导致内存溢出,这篇文章主要是介绍线程池的用法,线程池的线程执行原理将会在下一篇文章中介绍。
2. 线程的核心参数
要想知道线程的核心参数和组件是什么,我们直接去看线程的创建就知道了
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;
}
2.1.核心线程和最大线程
- 核心线程
corePoolSize
:在线程池中有有一些线程是创建出来之后就不会被回收,会在线程池中一直保持活跃的状态。核心线程的目的就是:确保有任务到来能够快速响应请求 - 最大线程数
maximumPoolSize
:线程池中允许的最大线程数。当任务数量超过核心线程数且工作队列已满时,线程池可以创建更多的线程,但总数不能超过 maximumPoolSize
下面是核心线程数和最大线程数的工作原理:
- 初始化:
- 当线程被创建出来的时候,核心线程数会被初始化为 0,所以并不是一开始就创建这么多线程存在线程池中
- 添加任务
- 随着任务被添加,核心线程数也会逐渐增加到
corePoolSize
,这时候再添加任务就会把这些任务加入到任务队列里面等待处理 - 当队列也放满任务的时候,新加入的任务会由线程池创建
非核心线程
去处理,当核心线程 + 非核心线程的数量
达到maximumPoolSize
的时候,再加入任务就会执行拒绝策略了
- 随着任务被添加,核心线程数也会逐渐增加到
- 线程回收
- 非核心线程在空闲一段时间之后(
keepAliveTime
)就会被回收 - 核心线程是不会被回收的,除非线程池关闭了
- 非核心线程在空闲一段时间之后(
2.2.任务队列
从 2.1 可以得知,任务队列就是存储那些没有被核心线程处理的任务,JDK 中有下面几种常见任务队列
2.2.1.ArrayBlockingQueue
- 类型: 有界阻塞队列(Bounded Blocking Queue)。
- 特点: 基于数组实现,容量固定不可修改
- 适用场景: 比较适合用于需要控制任务队列大小的场景,避免任务队列无限增长
2.2.2.LinkedBlockingQueue
- 类型: 可选的有界阻塞队列<.font>
- 特点: 基于链表实现,可以设置容量大小,如果不设置就默认创建一个无界队列
- 适用场景: 适用于任务数量波动较大,但希望避免任务队列无限增长的场景
2.2.3.SynchronousQueue
- 类型: 同步阻塞队列
- 特点:
没有容量
,也就是说每一次插入任务的时候必须要等到这个任务被执行了,才能继续往里面添加,有点像队列长度为 1 的生产者消费者模式 - 适用场景: 适用于任务提交和执行非常频繁的场景,任务提交后立即执行,不会在队列中等待
2.2.4.PriorityBlockingQueue
- 类型: 无界优先级阻塞队列(Unbounded Priority Blocking Queue)
- 特点: 基于优先级堆(数组)实现,可以按照设定的方式进行排序
- 适用场景: 适用于任务需要按照优先级顺序执行的场景
2.2.5.DelayQueue
- 类型: 无界延迟阻塞队列(Unbounded Delay Blocking Queue)
- 特点: 基于 PriorityQueue 实现的延时队列,任务必须在指定的延迟时间后才能被执行,队列中的任务按照延迟时间排序
- 适用场景: 适用于需要延迟执行任务的场景,例如定时任务
2.2.7.LinkedBlockingDeque
- 类型: 可选有界双端阻塞队列(Optional Bounded Blocking Deque)
- 特点: 基于链表实现,支持从队列的两端插入和移除任务,也可以设置初始容量和不设置初始容量,如果不设置默认容量是
Integer.MAX_VALUE
- 适用场景: 适用于需要从队列两端操作任务的场景
2.3 keepAliveTime
keepAliveTime
就是非核心线程的保活时间,也就说当添加任务的时候如果队列已经塞满了,这时候会创建非核心线程去执行任务,这些非核心线程的保活时间就是keepAliveTime
,超过这个时间,这些非核心线程就会被回收调
2.4 ThreadFactory
线程工厂,这是一个接口,用于创建新的线程
public interface ThreadFactory {Thread newThread(Runnable r);
}
线程池里面的线程就是通过这个接口创建出来的,我们可以自己设置一个线程工厂,然后自定义线程的名称、优先级、是否为后台线程(Daemon Thread)、线程组等…
举个例子,下面这段代码中我们自定义了一个任务队列
public class Pra {public static void main(String[] args) {// 自定义 ThreadFactoryThreadFactory customThreadFactory = new ThreadFactory() {private int count = 0;@Overridepublic Thread newThread(Runnable r) {Thread thread = new Thread(r);thread.setName("Thread-Count-" + count++); // 设置线程名称thread.setPriority(Thread.NORM_PRIORITY); // 设置线程优先级thread.setDaemon(false); // 设置是否为后台线程return thread;}};// 创建线程池,并使用自定义的 ThreadFactoryExecutorService executor = Executors.newFixedThreadPool(5, customThreadFactory);// 提交任务for (int i = 0; i < 10; i++) {executor.submit(() -> {System.out.println("Executing task on thread: " + Thread.currentThread().getName());try {Thread.sleep(1000); // 模拟任务执行时间} catch (InterruptedException e) {e.printStackTrace();}});}// 关闭线程池executor.shutdown();}}
结果输出如下:
可以看到,输出的线程名字都是我们自己定义的名字
2.5 拒绝策略
在使用线程池时,当线程池中的任务队列已满且无法再接受新的任务时,就会触发拒绝策略,Java 提供了几种内置的拒绝策略
- AbortPolicy
- 默认的拒绝策略,当任务无法提交的时候就会抛出
RejectedExecutionException
异常
- 默认的拒绝策略,当任务无法提交的时候就会抛出
/*** 拒绝策略: 直接抛异常*/
public static class AbortPolicy implements RejectedExecutionHandler {public AbortPolicy() { }public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {throw new RejectedExecutionException("Task " + r.toString() +" rejected from " +e.toString());}
}
下面看个例子,
- CallerRunsPolicy
- 当任务无法提交的时候就会把这个任务
交给调用线程执行
- 这样就能避免任务被丢弃,但是有可能会导致调用者线程被阻塞
- 当任务无法提交的时候就会把这个任务
/*** 拒绝策略: 如果线程池没有关闭,当前线程去运行*/
public static class CallerRunsPolicy implements RejectedExecutionHandler {public CallerRunsPolicy() { }public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {if (!e.isShutdown()) {r.run();}}
}
- DiscardPolicy
- 当任务无法提交时,直接丢弃该任务,不做任何处理
- 如果任务不重要就可以用这个拒绝策略直接丢弃
/*** 拒绝策略: 什么也不管*/public static class DiscardPolicy implements RejectedExecutionHandler {public DiscardPolicy() { }public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {}}
- DiscardOldestPolicy
- 当任务无法提交时,丢弃任务队列中最旧的任务,然后尝试重新提交当前任务
- 适合在需要尽快处理新任务的情况下使用
/*** 拒绝策略: 抛弃最早的一条任务,加入当前任务*/
public static class DiscardOldestPolicy implements RejectedExecutionHandler {public DiscardOldestPolicy() { }public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {// 丢弃最早的一条任务if (!e.isShutdown()) {e.getQueue().poll();e.execute(r);}}
}
下面看一个具体的例子,我们自己定义一个线程池,核心线程数是 1,最大线程数是 1,任务队列长度是 2,然后我们往里面塞 5 个任务,从定义可知这个线程池最多只能处理 3 个任务,所以最后两个任务会执行拒绝策略
public class Pra {public static void main(String[] args) {// 创建线程池,指定拒绝策略ThreadPoolExecutor executor = new ThreadPoolExecutor(1, // 核心线程数1, // 最大线程数60, // 线程空闲时间TimeUnit.SECONDS,new LinkedBlockingQueue<>(2), // 任务队列new ThreadPoolExecutor.AbortPolicy() // 拒绝策略);// 提交任务for (int i = 0; i < 5; i++) {final int index = i;executor.submit(() -> {System.out.println("Thread Name: " + Thread.currentThread().getName() + ", index: " + index);try {Thread.sleep(2000); // 模拟任务执行时间} catch (InterruptedException e) {e.printStackTrace();}});}// 关闭线程池executor.shutdown();}}
上述输出如下:
这就是第一个 AbortPolicy 的输出,抛出异常 RejectedExecutionException,其余三个输出分别如下:
- CallerRunsPolicy:调用线程执行
- DiscardPolicy:丢弃任务
- DiscardOldestPolicy:丢弃队列中最早的任务,也就是
index 1
和index 2
3. JDK 提供的几种默认的线程池实现
JDK 提供了几种默认的线程池实现,这些线程池适合用于各种不同的场景
3.1 newFixedThreadPool
用于创建一个包括无界队列的线程池,特点如下:
- 核心线程数和最大线程数相同,意味者线程池能处理的任务就是
核心线程数 + 队列长度
- 队列使用了
LinkedBlockingQueue
,长度没有设置,意味者里面用了一个无界队列,需要注意任务过多导致的内存溢出的问题
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(),threadFactory);}
3.2 newCachedThreadPool
用于创建一个没有核心线程的线程池,特点如下:
- 核心线程数为
0
,最大线程数是Integer.MAX_VALUE
,这意味着能处理的任务数没有限制,同时创建出来的线程60S
内没有处理任务就会被回收掉 - 队列使用了
SynchronousQueue
,不存放任务,需要注意线程创建过多导致的内存溢出的问题 - 适合处理大量短期任务
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(),threadFactory);}
3.3 newSingleThreadExecutor
创建一个单线程的线程池,所有任务将按照提交的顺序依次执行,特点如下:
- 核心线程数为
1
,最大线程数是1
,意味者只有一个线程 - 队列使用了
LinkedBlockingQueue
,容量没有限制,需要注意任务过多导致的内存溢出的问题 - 适合用于对执行顺序有要求的任务
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));}
3.4 newScheduledThreadPool
创建一个可调度任务的线程池,适用于需要延迟执行或定期执行任务的场景,特点如下:
- 核心线程数可设置,最大线程数是
Integer.MAX_VALUE
,意味者可以接收的任务没有限制 - 队列使用了
DelayedWorkQueue
,支持延迟执行和定期执行任务,需要注意线程过多导致的内存溢出的问题 - 适合用于执行一些定时任务的场景,比如定时提醒…
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {return new ScheduledThreadPoolExecutor(corePoolSize);}public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());}
4. 为什么不推荐使用上面的线程池
虽然 JDK 给我们提供了这几个线程池的创建方法,但是或多或少都有一些局限,有可能会导致 性能问题
或者 内存溢出
的问题
- 任务队列无界
- 可以看到上面的这几个线程池中
newFixedThreadPool
和newSingleThreadExecutor
创建的都是无界队列,这就导致当任务比较多的时候都堵塞在任务队列里面有可能导致内存溢出
- 可以看到上面的这几个线程池中
- 线程数没有限制
- 剩下两个线程池
newCachedThreadPool
和newScheduledThreadPool
的线程数都是没有限制的,这就导致当任务比较多的时候创建太多的线程去执行任务有可能导致内存溢出
- 剩下两个线程池
- 参数无法自定义
- 默认线程池没有提供任务优先级的支持和定制化的拒绝策略
- 在高并发场景下,可能需要根据任务的紧急程度、重要性等因素来排队或拒绝某些任务,而默认线程池无法满足这些需求
- 同时线程池里面我们也没办法自己设置线程的名称等属性…
总之还有很多的限制这里就不说了,我们可以通过自定义线程池参数的方式去更好控制线程池的行为,满足具体应用的要求,设计到下面几个方面:
- 合理设置线程数量,根据系统的 CPU 核心数和任务类型(CPU 密集型或 I/O 密集型),合理设置线程池的核心线程数和最大线程数
- 有界任务队列,限制任务队列大小,避免无限制增加
- 自定义拒绝策略,一般我自己在工作中写的话都会用到第二种策略,就是让调用线程去执行
- 线程工厂,通过工厂去自定义线程的命名、优先级等属性,便于调试和监控
/*** 构造函数*/public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {// 参数设置if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}
可以通过上面的构造函数去自己设定合理的参数,构建线程池
5. 小结
到这里就介绍完核心线程的一些参数和用法了,其实线程池的使用很简单,但是里面的一些原理流程还是值得深究的,就比如下面两个问题:
- 线程池是如何做到核心线程不回收,非核心线程回收的?
- 线程池的任务执行流程是怎么样的?
- 执行任务的过程中发生异常了,会发生什么?
这些问题都需要从源码中才能找到答案了,下一篇文章我将会详细讲解线程池的源码
如有错误,欢迎指出!!!
相关文章:
详细说说 JDK 的线程池的创建参数
文章目录 1. 概要2. 线程的核心参数2.1.核心线程和最大线程2.2.任务队列2.2.1.ArrayBlockingQueue2.2.2.LinkedBlockingQueue2.2.3.SynchronousQueue2.2.4.PriorityBlockingQueue2.2.5.DelayQueue2.2.7.LinkedBlockingDeque 2.3 keepAliveTime2.4 ThreadFactory2.5 拒绝策略 3.…...
惠普电脑切换默认F1至F12快捷键,FN切换
发现新买的惠普电脑,按F1至F12发现是快捷功能键,而按fnF1至F12才是windows的功能键和正常我自己使用的电脑刚好相反,实在太不方便了。 解决办法需要进入biso里面去把功能键模式选中给关掉,才能恢复回来...
RabbitMQ在手动消费的模式下设置失败重新投递策略
最近在写RabbitMQ的消费者,因为业务需求,希望失败后重试一定次数,超过之后就不处理了,或者放入死信队列。我这里就达到重试次数后就不处理了。本来以为很简单的,问了kimi,按它的方法配置之后,发…...
[巅峰极客 2021]签到
[巅峰极客 2021]签到 给了我们好多表情,真的是一脸懵逼 注意给我们的关键词 GAME 现在还不知道是什么意思我们去试着解开一下 用这个emoji表情解密器,这里我找了好久才找到一个 emoji-aes 这里的Key值就是GAME 运行后出现flag NSSCTF{10ve_4nd_Peace…...
CrystalDiskInfo:硬盘健康监测工具简介和下载
原论坛给你更好的阅读体验:CrystalDiskInfo:硬盘健康监测工具简介和下载 | 波波论坛 引言 在日常使用电脑时,硬盘的健康状态对于系统的稳定性和数据的安全性至关重要。硬盘出现故障可能会导致数据丢失,严重时甚至会使整个系统无…...
循环神经网络(RNN)详解
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
vue基础之3:模板语法、数据绑定
欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…...
Ubuntu通过脚本启动多个可执行文件
Ubuntu通过脚本启动多个可执行文件 在 Ubuntu 中,可以通过一个脚本启动多个可执行文件,同时支持顺序执行、并行执行或特定条件下的执行。以下是实现的详细方法: 1. 创建脚本文件 首先,创建一个脚本文件,例如 start_p…...
【C++】LeetCode:LCR 026. 重排链表
题干 LCR 026. 重排链表 给定一个单链表 L 的头节点 head ,单链表 L 表示为: L0 → L1 → … → Ln-1 → Ln 请将其重新排列后变为: L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → … 不能只是单纯的改变节点内部的值,而是需要实…...
文档加密怎么做才安全?
公司的文档包含很多机密文件,这些文件不仅关乎公司的核心竞争力,还涉及到客户隐私、商业策略等敏感信息。因此,文档的保管和传递一直是我们工作的重中之重。 为了确保机密文件的安全,公司需要制定了一系列严格的保密措施。从文件的…...
CTF之WEB(php弱类型绕过)
PHP 的弱类型特性有时会导致意外的行为,特别是在类型比较时。这些特性可以被利用来绕过一些预期的安全检查。以下是一些常见的 PHP 弱类型绕过技巧及其解释: 类型介绍 1. 类型比较 ( vs ) 在 PHP 中, 是松散比较,而 是严格比较…...
Java ConcurrentHashMap
Java Map本质不是线程安全的,HashTable和Collections同步包装器(Synchronized Wrapper)在并发场景下性能低。Java还为实现 Map 的线程安全提供了并发包,保证线程安全的方式从synchronize简单方式到精细化,比如Concurre…...
力扣162:寻找峰值
峰值元素是指其值严格大于左右相邻值的元素。 给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。 你可以假设 nums[-1] nums[n] -∞ 。 你必须实现时间复杂度为 O(…...
网络设备配置指南:交换机、路由器与防火墙的基础配置与管理
在现代网络管理中,交换机、路由器和防火墙是不可或缺的关键设备。掌握这些设备的基本配置与管理,对于确保网络的稳定性、安全性和高效性至关重要。本文将详细介绍交换机、路由器和防火墙的基础配置与管理,并通过代码示例和图示来帮助读者更好地理解和应用。 一、交换机的基…...
parallelStream并行流使用踩坑,集合安全
parallelStream并行流使用踩坑 parallelStream介绍 parallelStream实现的是多线程处理从而实现并行流,相较于stream的单行流处理数据的速度更快,看一下其源码会发现parallelStream是使用线程池ForkJoin来调度的。 而ForkJoinPool的默认线程数是CPU核数 …...
清远榉之乡托养机构探讨:自闭症的本质辨析
当人们谈及自闭症时,常常会产生一个疑问:自闭症是精神类疾病吗?今天,清远榉之乡托养机构就来为大家解开这个疑惑。 榉之乡大龄自闭症托养机构在江苏、广东、江西等地都有分校,一直致力于为大龄自闭症患者提供专业的支持…...
音视频入门基础:MPEG2-TS专题(10)——PAT简介
一、引言 当某个transport packet的TS Header中的PID属性的值为0x0000时,该transport packet的payload为Program association table ,即 PAT表。PAT表包含所有PMT表的目录列表,将program_number和PMT表的PID相关联,获取数据的起始…...
wordpress网站首页底部栏显示网站备案信息
一、页脚文件footer.php 例如,wordpress主题使用的是simple-life主题,服务器IP为192.168.68.89,在wordpress主题文件中有个页脚文件footer.php,这是一个包含网站页脚代码的文件。 footer.php 路径如下: /www/wwwroot/192.168.68…...
SOLIDWORKS英文,怎么修改成中文
SOLIDWORKS英文,怎么修改成中文 打开控制面板里的程序 选择程序与功能 找到SOLIDWORKS,选择并点击上方 “更改” 在跳出来的更改页面,选择“简体中文” 点击SOLIDWORKS界面上小齿轮,进入设置 取消勾选English两个相关设置 重启SO…...
简单搭建qiankun的主应用和子应用并且用Docker进行服务器部署
在node18环境下,用react18创建qiankun主应用和两个子应用,react路由用V6版本,都在/main路由下访问子应用,用Dockerfile部署到腾讯云CentOS7.6服务器的8000端口进行访问,且在部署过程中进行nginx配置以进行合理的路由访…...
等保三级安全架构设计方案
一、概述 等保三级,全称为“信息系统安全等级保护三级”,是根据信息安全保护的需求,将系统的安全保护划分为五个等级中的第三级,主要针对相对重要的信息系统进行保护。根据《信息系统安全等级保护基本要求》(GB/T 222…...
【Stable Diffusion】安装教程
目录 一、python 安装教程 二、windows cuda安装教程 三、Stable Diffusion下载 四、Stable Diffusion部署(重点) 一、python 安装教程 (1)第一步下载 打开python下载页面,找到python3.10.9,点击右边…...
05—如何设计和仿真阻抗匹配网络
如何设计和仿真阻抗匹配网络 1. 介绍 在设计电路时,大部分同学只是想把布局布置的更专业,可能没有考虑串扰、电源完整性或阻抗匹配等问题。当了解天线和其他射频设备的匹配网络后,才会意识到阻抗匹配在高速和高频电路中的重要性。 但是,什么时候应该使用阻抗匹配网络?哪…...
Trimble X12助力电力管廊数据采集,为机器人巡视系统提供精准导航支持
地下电缆是一个城市重要的基础设施,它不仅具有规模大、范围广、空间分布复杂等特点,更重要的是它还承担着信息传输、能源输送等与人们生活息息相关的重要功能,也是一个城市赖以生存和发展的物质基础。 01、项目概述 本次项目是对某区域2公里左…...
新质驱动·科东软件受邀出席2024智能网联+低空经济暨第二届湾区汽车T9+N闭门会议
为推进广东省加快发展新质生产力,贯彻落实“百县千镇万村高质量发展工程”,推动韶关市新丰县智能网联新能源汽车、低空经济与数字技术的创新与发展,充分发挥湾区汽车产业链头部企业的带动作用。韶关市指导、珠三角湾区智能网联新能源汽车产业…...
UE5_建立自己的资产库
资产库需要用到一个插件: UAsset Browser - 直接在当前项目预览其他UE项目资产(.uasset 文件) - 直接迁移其他UE项目资产到当前项目 - 不用另外打开资产项目查看资产,迁移资产(麻烦) 插件官网插件文档插…...
Matlab搜索路径添加不上
发现无论是右键文件夹添加到路径,还是在“设置路径”中专门添加,我的路径始终添加不上,导致代码运行始终报错,后来将路径中的“”加号去掉后,就添加成功了,经过测试,路径中含有中文也可以添加成…...
跨UI发送信号
如何自定义信号 1.使用signals声明 2.返回值是void 3.在需要发送的地方使用 emit 信号名字(参数); 进行发送 4.在需要链接的地方使用connect进行链4 接 signals:void sig_addOne(int value); connect(&dlg,&SetDialog::sig_addOne,[](int value){ui->lineEdit…...
宠物领养平台构建:SpringBoot技术路线图
摘 要 如今社会上各行各业,都在用属于自己专用的软件来进行工作,互联网发展到这个时候,人们已经发现离不开了互联网。互联网的发展,离不开一些新的技术,而新技术的产生往往是为了解决现有问题而产生的。针对于宠物领养…...
uniapp App端在renderjs层渲染echarts获取不到service层id的问题
报错信息:Cannot read properties of undefined (reading id) at app-view.js 这样的写法App端有时在renderjs视图层获取不到server逻辑层的数据 server层 renderjs层 解决方法:需要把数据(id)通过server层向renderjs层传值 server层 renderjs层...
标准输入输出函数scanf()/gets()/printf()/puts()的功能和区别
前言: 这两个函数都是用来从标准输入设备(通常是键盘)读取字符串的,但是它们有一些区别和注意事项。 scanf函数 scanf函数是C语言中的一个输入函数,它可以按照指定的格式从标准输入设备(通常是键盘&#…...
JavaScript 中的原型和原型链
JavaScript 中的原型和原型链也是一个相对较难理解透彻的知识点,下面结合详细例子来进行说明: 一、原型的概念 在 JavaScript 中,每个函数都有一个 prototype 属性,这个属性指向一个对象,这个对象就是所谓的 “原型对…...
tensorflow.python.framework.errors_impl.FailedPreconditionError
以下是我的报错 Traceback (most recent call last):File "e:\tool\anaconda\envs\openmmlab\lib\runpy.py", line 194, in _run_module_as_mainreturn _run_code(code, main_globals, None,File "e:\tool\anaconda\envs\openmmlab\lib\runpy.py", line 8…...
lua-cjson 例子
apt install -y lua-cjson 安装 编辑 tmp.lua cjson require "cjson" p 666 d "23.42" payload{"d":[{"pres":..(p)..,"temp":"..(d).."}]} print("payload " .. payload) j cjson.decode(payloa…...
《白帽子讲Web安全》15-16章
《白帽子讲Web安全》15-16章 《白帽子讲Web安全》15章15、Web Server配置安全15.1、Apache安全15.2、Nginx安全15.3、jBoss远程命令执行15.4、Tomcat远程命令执行15.5、HTTP Parameter Pollution15.6、小结 第四篇 互联网公司运营安全《白帽子讲Web安全》16章16、互联网业务安全…...
挑战用React封装100个组件【001】
项目地址 https://github.com/hismeyy/react-component-100 组件描述 组件适用于需要展示图文信息的场景,比如产品介绍、用户卡片或任何带有标题、描述和可选图片的内容展示 样式展示 代码展示 InfoCard.tsx import ./InfoCard.cssinterface InfoCardProps {ti…...
在 macOS 上安装 MongoDB Community Edition
https://www.mongodb.com/zh-cn/docs/manual/tutorial/install-mongodb-on-os-x/...
网络安全运行与维护高级 - 题库汇总百题
1. 单选题 内部信息安全管理组织中的()担负保护系统安全的责任,但工作重点偏向于监视系统的运行情况,并且对安全管理制度的贯彻执行情况进行监督和检查。 A. 安全审查和决策机构 B. 安全主管机构 C. 安全运行维护机构 D. 安全审计机构 正确答案:D 2. 单选题 下列那…...
在html页面显示一个变量,而这个变量中有xss脚本,如何安全的把这个变量原样展示出来
当你想要在HTML页面安全地展示一个可能包含XSS(跨站脚本攻击)脚本的变量原样内容时,可以通过以下几种常见的方式来实现安全展示: 方法一:使用文本节点 在JavaScript中,当你要将变量插入到HTML页面的某个元…...
【Linux】TCP网络编程
目录 V1_Echo_Server V2_Echo_Server多进程版本 V3_Echo_Server多线程版本 V3-1_多线程远程命令执行 V4_Echo_Server线程池版本 V1_Echo_Server TcpServer的上层调用如下,和UdpServer几乎一样: 而在InitServer中,大部分也和UDP那里一样&…...
openGauss你计算的表大小,有包含toast表么?
openGauss你计算的表大小,有包含toast表么? 最近有一个同事问我说“openGauss中pg_relation_size函数在计算表的大小时是否包含了大字段的大小?”,经过思考后,自己觉得表的大小是不包含大字段的大小的,然后…...
Python字典的用法(定义、增加、删除、修改、查询、遍历)
一.字典的介绍 dictionary(字典)是除了列表以外的 Python 中最灵活的数据类型。dict(字典)可以采用多个数据,通常用于存储描述一个物体的相关信息。 字典和列表最主要的区别是,字典是无序的对象集合&#x…...
分布式锁的实现原理
作者:来自 vivo 互联网服务器团队- Xu Yaoming 介绍分布式锁的实现原理。 一、分布式锁概述 分布式锁,顾名思义,就是在分布式环境下使用的锁。众所周知,在并发编程中,我们经常需要借助并发控制工具,如 mute…...
linux(centos) 环境部署,安装JDK,docker(mysql, redis,nginx,minio,nacos)
目录 1.安装JDK (非docker)1.1 将文件放在目录下: /usr/local/jdk1.2 解压至当前目录1.3 配置环境变量 2.安装docker2.1 验证centos内核2.2 安装软件工具包2.3 设置yum源2.4 查看仓库中所有docker版本,按需选择安装2.5 安装docker2.6 启动docker 并 开机…...
批量生成不同用户的pdf 文件(html样式)
技术 selenium thymeleaf itextpdf chromedriver 使用thymeleaf 将动态数据替换 使用selenium chromedriver 进行js ,css等逻辑运算后渲染视图 使用itextpdf 将html 转为pdf 文件 html模板 <!DOCTYPE html> <html xmlns:th"http://www.thymeleaf…...
常见的排序算法
一、基于比较的排序算法 基于比较的排序算法通过比较元素之间的大小来完成排序。 1.1 冒泡排序(Bubble Sort) 特点:通过多次交换相邻元素,将最大(或最小)元素“冒泡”到序列末端。时间复杂度:…...
从语法、功能、社区和使用场景来比较 Sass 和 LESS
一:可以从语法、功能、社区和使用场景来比较 Sass 和 LESS: 1:语法 原始的 Sass 采用的是缩进而不是大括号,后续的 Sass 版本与 LESS 一样使用与 CSS 类似的语法: address {.fa.fa-mobile-phone {margin: 0 3px 0 2…...
hdlbits系列verilog解答(Exams/m2014 q4b)-87
文章目录 一、问题描述二、verilog源码三、仿真结果一、问题描述 本节学习如何实现下图中的电路。 模块声明 module top_module ( input clk, input d, input ar, // asynchronous reset output q); 思路: 只是实现一种带异步复位的D触发器。 时钟边沿两种触发方式的关键字…...
Python 和 Pyecharts 对Taptap相关数据可视化分析
结果展示: 数据来源: Python爬取TapTap 热门游戏信息并存储到数据库(详细版) 目录 结果展示: 数据来源: Python爬取TapTap 热门游戏信息并存储到数据库(详细版 一、引言 二、准备工作 三、…...
系统学习算法: 专题二 滑动窗口
题目一: 算法原理: 依然第一反应是暴力枚举,将所有的子数组都枚举出来,找到满足条件的长度最小的子数组,但是需要两层循环,时间复杂度来到O(N^2) 接下来就该思考如何进行优化 如果…...