Spring Boot 线程池自定义拒绝策略:解决任务堆积与丢失问题
如何通过自定义线程池提升系统稳定性
背景
在高并发系统中,线程池管理至关重要。默认线程池可能导致:
- 资源浪费(创建过多线程导致 OOM)
- 任务堆积(队列满后任务被拒绝)
- 任务丢失(默认拒绝策略丢弃任务
为了防止这些问题,我们使用 Spring Boot 自定义线程池,并优化 异常处理 和 拒绝策略。
线程池方案设计
在 ExecutorConfig 类中,我们定义了两个线程池:
- myExecutor:用于普通任务,采用CallerRunsPolicy 避免任务丢失。
- oneExecutor:用于信号计算任务(单线程模式),具有 自定义异常处理 和 阻塞式拒绝策略。
代码解析
线程池 myExecutor(通用任务池)
@Bean(name = "myExecutor")
public Executor myExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(threadProperties.getCorePoolSize());executor.setMaxPoolSize(threadProperties.getMaxPoolSize());executor.setQueueCapacity(threadProperties.getQueueCapacity());executor.setThreadNamePrefix("signal-executor-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());executor.initialize();return executor;
}
设计要点:
CallerRunsPolicy:线程池满了,主线程执行任务,防止丢失但可能影响性能。
线程池 oneExecutor(单线程计算池)
@Bean(name = "oneExecutor")
public Executor oneExecutor() {ThreadFactory threadFactory = new BasicThreadFactory.Builder().uncaughtExceptionHandler(new MyThreadException()).namingPattern("one-thread-%s").build();ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(1);executor.setMaxPoolSize(1);executor.setQueueCapacity(1);executor.setThreadFactory(threadFactory);executor.setThreadGroup(new ThreadGroup("1"));executor.setRejectedExecutionHandler(new CustomRejectedExecutionHandler());executor.initialize();return executor;
}
设计要点:
单线程池(保证任务顺序执行),如果无须,那就按照当前的服务节点配置来设置参数
自定义异常处理(防止线程因异常崩溃)
自定义拒绝策略(任务队列满时阻塞等待)
自定义异常处理
class MyThreadException implements Thread.UncaughtExceptionHandler {@Overridepublic void uncaughtException(Thread t, Throwable e) {log.error("异常: {},线程: {}", ExceptionUtils.getStackTrace(e), t.getName());}
}
作用:防止线程因未捕获异常直接终止,提升系统稳定性。当然这个是处理线程池中子任务处理业务逻辑的时候发生业务异常的处理方式,除此之外还有其他的解决方案
异常处理
- afterExecute() 处理异常(可扩展) :用于处理执行过程中抛出的异常
- uncaughtExceptionHandler 处理未捕获异常(默认 JVM 打印堆栈): 用于处理线程未捕获的异常;
- RejectedExecutionHandler 处理任务拒绝:处理任务被拒绝的情况。
处理顺序:
- 当任务执行时,如果任务抛出异常,它会首先被 afterExecute() 捕获,并且你可以在这里进行进一步的处理。
- 如果任务中的异常没有被 afterExecute() 捕获或处理,且是未捕获异常,它会交由 uncaughtExceptionHandler 进行处理。
- RejectedExecutionHandler 是处理线程池拒绝接受新任务的情况,这通常和任务执行过程中的异常无关,主要处理线程池饱和时的情况。
注意:beforeExecute() 在任务开始执行前调用,通常用于准备工作;
异常处理上,beforeExecute() 不会直接处理任务执行过程中的异常,但可以捕获并处理自己内部的异常;
相关源码分析:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
// 1️⃣ 线程池当前线程数 < corePoolSize,则尝试新增核心线程执行任务
if (workerCountOf© < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
// 2️⃣ 线程池已满,尝试加入工作队列
if (isRunning© && workQueue.offer(command)) {
int recheck = ctl.get();
if (!isRunning(recheck) && remove(command))
reject(command); // 任务队列中的任务被拒绝
else if (workerCountOf(recheck) == 0)
addWorker(null, false); // 防止线程池为空,确保有线程执行任务
}
// 3️⃣ 线程池满且队列满,尝试新增非核心线程
else if (!addWorker(command, false))
reject(command); // 线程池已满,拒绝任务
}
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // 允许中断
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// 1️⃣ 执行任务
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run(); // ⚠ 任务执行点
} catch (RuntimeException x) {
thrown = x;
throw x;
} catch (Error x) {
thrown = x;
throw x;
} catch (Throwable x) {
thrown = x;
throw new Error(x);
} finally {
afterExecute(task, thrown); // 2️⃣ 任务执行后的扩展方法
}
task = null;
w.completedTasks++;
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly); // 3️⃣ 任务异常退出,删除该线程
}
}
自定义拒绝策略-重新放回队列中
public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {try {if (!executor.isShutdown()) {log.info("队列已满,阻塞等待...");executor.getQueue().put(r);log.info("任务已加入队列");}} catch (Exception e) {log.error("拒绝策略异常", e);}}
}
作用:
默认拒绝策略丢弃任务,而此策略会阻塞等待,确保任务不丢失。
适用于任务量较大,但不能丢失任务的场景(如消息队列处理)
自定义拒绝策略-主线程执行
/*** 自定义线程池,防止使用默认线程池导致内存溢出** @param* @return* @author bu.junjie* @date 2021/11/10 10:00*/@Bean(name = "myExecutor")public Executor myExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(threadProperties.getCorePoolSize());executor.setMaxPoolSize(threadProperties.getMaxPoolSize());executor.setQueueCapacity(threadProperties.getQueueCapacity());executor.setThreadNamePrefix("signal-executor-");// 使用此策略,如果添加到线程池失败,那么主线程会自己去执行该任务,不会等待线程池中的线程去执行,阻塞主线程executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());executor.initialize();return executor;}
适用场景
✅ 高并发请求(如 HTTP 任务)
✅ 后台数据处理(如日志分析、批量计算)
✅ 长时间任务(如大文件处理、消息队列消费)
总结
- 自定义线程池 防止资源浪费,提升吞吐量。
- 异常处理 避免线程因未捕获异常而终止。
- 优化拒绝策略 防止任务丢失,提高系统可靠性。
线程池优化是高并发系统的关键,希望本篇博客能帮助你更好地理解和应用线程池! 🚀🚀🚀
完整代码示例
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import javax.annotation.Resource;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;/*** 线程池配置参数** @version 1.0.0* @createTime 2025-11-09 14:01*/
@Configuration
@EnableAsync
@Slf4j
public class ExecutorConfig {@Resourceprivate ThreadProperties threadProperties;/*** 自定义线程池,防止使用默认线程池导致内存溢出** @param* @return* @author bu.junjie* @date 2021/11/10 10:00*/@Bean(name = "myExecutor")public Executor myExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(threadProperties.getCorePoolSize());executor.setMaxPoolSize(threadProperties.getMaxPoolSize());executor.setQueueCapacity(threadProperties.getQueueCapacity());executor.setThreadNamePrefix("signal-executor-");// 使用此策略,如果添加到线程池失败,那么主线程会自己去执行该任务,不会等待线程池中的线程去执行,阻塞主线程executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());executor.initialize();return executor;}/*** 信号计算时的线程池(1号线程池)** @param* @return* @author bu.junjie* @date 2022/1/5 13:01*/@Bean(name = "oneExecutor")public Executor oneExecutor() {ThreadFactory threadFactory = new BasicThreadFactory.Builder().uncaughtExceptionHandler(new MyThreadException()).namingPattern("one-thread-%s").build();ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(1);executor.setMaxPoolSize(1);executor.setThreadFactory(threadFactory);executor.setQueueCapacity(1);executor.setThreadGroup(new ThreadGroup("1"));executor.setRejectedExecutionHandler(new CustomRejectedExecutionHandler());executor.initialize();return executor;}class MyThreadException implements Thread.UncaughtExceptionHandler {/*** Method invoked when the given thread terminates due to the* given uncaught exception.* <p>Any exception thrown by this method will be ignored by the* Java Virtual Machine.** @param t the thread* @param e the exception*/@Overridepublic void uncaughtException(Thread t, Throwable e) {log.error("MyThreadException is exception=【{}】,Thread = 【{}】", ExceptionUtils.getStackTrace(e), t.getName());}}/*** 拒绝策略优化** @param* @author bu.junjie* @date 2022/1/8 14:06* @return*/public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {try {// 核心改造点,由blockingqueue的offer改成put阻塞方法if (!executor.isShutdown()) {long start = System.currentTimeMillis();log.info("当前阻塞队列已满开始请求存放队列束!!!");executor.getQueue().put(r);log.info("存放阻塞队列成功,阻塞时间time = 【{}】", System.currentTimeMillis() - start);}} catch (Exception e) {e.printStackTrace();}}}}
思考
为什么拒绝策略要重新抛出异常?
我们会发现默认的四种拒绝策略在处理完业务逻辑之后还会重新抛出异常,就算你是自定义的拒绝策略也需要重新抛出异常,为什么呢?不抛出会怎么样?
如果不抛出异常,调用方(业务代码)无法感知任务被拒绝,可能导致任务丢失或业务逻辑异常。
场景分析
当线程池队列满了时,会触发 rejectedExecution 方法。如果我们只是记录日志,而不抛出异常:
- 主线程会继续执行,但任务并未真正执行,业务方无法感知到这个问题。
- 可能导致数据丢失,尤其是在关键业务(如支付、订单、消息处理)场景中。
重新抛出异常的好处
✅ 保证调用方可以感知任务拒绝,决定是否降级处理、重试或报警。
✅ 防止静默丢失任务,保证业务的可靠性。
✅ 与 Spring 线程池默认行为保持一致,防止意外吞掉异常。
代码示例
❌ 错误示例(未抛出异常,可能导致任务丢失)
public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {try {if (!executor.isShutdown()) {log.warn("队列已满,任务阻塞等待...");executor.getQueue().put(r); // 可能抛出异常log.info("任务已放入队列");}} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 仅恢复中断状态,但未通知调用方}}
}
问题:
调用方不会收到异常,以为任务已经成功执行,但其实可能丢失了。
例如,在支付系统中,如果订单更新任务丢失,可能导致订单状态未更新。
✅ 正确示例(重新抛出异常,保证调用方可感知)
public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {try {if (!executor.isShutdown()) {log.warn("队列已满,阻塞等待...");executor.getQueue().put(r);log.info("任务成功进入队列");return; // 任务成功加入队列后不需要抛异常}} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 恢复线程中断状态throw new RejectedExecutionException("任务提交被中断", e);} catch (Exception e) {log.error("任务拒绝策略发生异常", e);throw new RejectedExecutionException("自定义拒绝策略异常", e);}}
}
改进点:
任务成功放入队列时不会抛异常,避免不必要的错误。
如果 put() 失败,抛出 RejectedExecutionException,让业务方感知。
捕获 InterruptedException 并恢复中断状态,避免影响后续任务。
其实这个原因和为什么需要恢复线程中断一样的逻辑,也是为了让调用方感知到
业务方如何处理异常?
如果 rejectedExecution 抛出 RejectedExecutionException,业务代码可以捕获异常并进行降级,例如:
try {executor.execute(task);
} catch (RejectedExecutionException e) {log.error("线程池已满,任务执行失败,进行降级处理", e);// 业务降级策略,例如:saveToDatabaseForLaterProcessing(task);
}
降级方案:如果线程池拒绝任务,可以存入 数据库、MQ 或 重试队列,避免任务丢失。
结论
🚀 必须重新抛出异常,否则:
- 任务可能悄悄丢失,业务方无法感知。
- 可能影响数据一致性(如支付、订单、日志处理)。
- 业务代码无法主动补救(重试、降级等)。
最佳实践:
- 成功放入队列 → 不抛异常
- 任务无法处理 → 抛出 RejectedExecutionException,让调用方感知
这样可以既保证任务不丢失,又确保调用方有能力处理拒绝任务!🔥
自定义拒绝策略put()方法?
其实默认拒绝策略是offer()方法是非阻塞的,也就是只要队列中的任务只要有,那就去创建子线程,直至触发拒绝策略
✅ 正确示例
public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {try {System.out.println("队列已满,阻塞等待...");executor.getQueue().put(r); // 阻塞等待队列有空位System.out.println("任务重新加入队列:" + r.toString());} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RejectedExecutionException("任务提交失败,线程被中断", e);}}
}
相关文章:
Spring Boot 线程池自定义拒绝策略:解决任务堆积与丢失问题
如何通过自定义线程池提升系统稳定性 背景 在高并发系统中,线程池管理至关重要。默认线程池可能导致: 资源浪费(创建过多线程导致 OOM)任务堆积(队列满后任务被拒绝)任务丢失(默认拒绝策略丢…...
C++17 新特性解析
C++17 是 C++ 标准的一个重要更新,它在 C++11/14 的基础上引入了许多新特性,进一步简化了代码编写、提升了性能和类型安全性。以下是 C++17 的主要特性分类介绍: 一、语言核心改进 1. 结构化绑定(Structured Bindings) 允许将元组、结构体或数组的成员直接解包到变量中。…...
支持向量机相关文献
根据最新的研究动态和文献综述,当前支持向量机(SVM)的研究方向和内容主要集中在以下几个方面: 1. 提高训练效率 并行计算与分布式计算:随着数据规模的增加,SVM的训练时间往往较长,难以满足实时…...
线上hbase rs 读写请求个数指标重置问题分析
问题描述: 客户想通过调用hbase的jmx接口获取hbase的读写请求个数,以此来分析HBase读写请求每日增量。 但是发现生产,测试多个集群,Hbase服务指标regionserver读写请求个数存在突然下降到0或者大幅度下降情况。 需要排查原因: 某个Region的读写请求数:会发现经常会重置为…...
USB子系统学习(四)用户态下使用libusb读取鼠标数据
文章目录 1、声明2、HID协议2.1、描述符2.2、鼠标数据格式 3、应用程序4、编译应用程序5、测试6、其它 1、声明 本文是在学习韦东山《驱动大全》USB子系统时,为梳理知识点和自己回看而记录,全部内容高度复制粘贴。 韦老师的《驱动大全》:商…...
WPF 设置宽度为 父容器 宽度的一半
方法1:使用 绑定和转换器 实现 创建类文件 HalfWidthConverter public class HalfWidthConverter : IValueConverter{public object Convert(object value, Type targetType, object parameter, CultureInfo culture){if (value is double width){return width / 4…...
网络工程师 (30)以太网技术
一、起源与发展 以太网技术起源于20世纪70年代,最初由Xerox公司的帕洛阿尔托研究中心(PARC)开发。最初的以太网采用同轴电缆作为传输介质,数据传输速率为2.94Mbps(后发展为10Mbps),主要用于解决…...
2025.2.11
1> 制作一个闹钟软件 .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QLabel> #include <QLineEdit> #include <QPushButton> #include <QTime> #include <QTimer> #include <QTimeEdit> #include <QDa…...
HTML应用指南:利用POST请求获取接入比亚迪业态的充电桩位置信息
在新能源汽车快速发展的今天,充电桩的分布和可用性成为了影响用户体验的关键因素之一。比亚迪作为全球领先的新能源汽车制造商,不仅在车辆制造方面取得了卓越成就,也在充电基础设施建设上投入了大量资源。为了帮助用户更方便地找到比亚迪充电桩的位置,本篇文章,我们将探究…...
系统URL整合系列视频四(需求介绍补充)
视频 系统URL整合系列视频四(需求补充说明) 视频介绍 (全国)大型分布式系统Web资源URL整合需求(补充)讲解。当今社会各行各业对软件系统的web资源访问权限控制越来越严格,控制粒度也越来越细。…...
PRC框架-Dubbo
RPC框架 RPC(Remote Procedure Call,远程过程调用)框架是一种允许客户端通过网络调用服务器端程序的技术。以下是常见的RPC框架及其特点: 1. 基于HTTP/REST的RPC框架 特点:简单易用,与Web开发无缝集成&am…...
Win10环境借助DockerDesktop部署最新MySQL9.2
Win10环境借助DockerDesktop部署最新MySQL9.2 前言 作为一杆主要撸Java的大数据平台开发攻城狮,必不可少要折腾各种组件,环境和版本一直是很头疼的事情。虽然可以借助Anaconda来托管Python的环境,也可以使用多个虚拟机来部署不同的环境&…...
PlantUML 总结
PlantUML 总结 1. 概述 PlantUML 是一个开源工具,允许用户通过简单的文本描述来生成各种UML图表。它支持多种图表类型,包括但不限于序列图、用例图、类图、活动图等。 2. 基本概念 2.1 开始和结束标记 startuml 和 enduml:用于标记Plant…...
【Elasticsearch】监控与管理:集群监控指标
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
Swift的方法派发机制
1. 静态派发(Static Dispatch) 静态派发在编译时确定方法的具体实现,调用时直接跳转到该实现。静态派发的优点是性能高,因为不需要运行时查找方法实现。 适用场景: 值类型(Struct 和 Enum)&am…...
4.python+flask+SQLAlchemy+达梦数据库
前提 1.liunx Centos7上通过docker部署了达梦数据库。从达梦官网下载的docker镜像。(可以参考前面的博文) 2.windows上通过下载x86,win64位的达梦数据库,只安装客户端,不安装服务端。从达梦官网下载达梦数据库windows版。(可以参考前面的博文) 这样就可以用windows的达…...
6.深度学习在推荐系统中的应用
接下来我们将学习深度学习在推荐系统中的应用。深度学习技术近年来在推荐系统中得到了广泛应用,能够有效提升推荐系统的性能和精度。在这一课中,我们将介绍以下内容: 深度学习在推荐系统中的优势常用的深度学习推荐模型深度学习推荐系统的实…...
Leetcode - 149双周赛
目录 一、3438. 找到字符串中合法的相邻数字二、3439. 重新安排会议得到最多空余时间 I三、3440. 重新安排会议得到最多空余时间 II四、3441. 变成好标题的最少代价 一、3438. 找到字符串中合法的相邻数字 题目链接 本题有两个条件: 相邻数字互不相同两个数字的的…...
ArrayList、LinkedList、HashMap、HashTable、HashSet、TreeSet
集合族谱 在这些集合中,仅有vector和hashtable是线程安全的,其内部方法基本都有synchronized修饰。 ArrayList 底层采用Object数组实现,实现了RandomAccess接口因此支持随机访问。插入删除操作效率慢。 ArrayList需要一份连续的内存空间。 A…...
在 Windows 系统中如何快速进入安全模式的两种方法
在使用电脑的过程中,有时我们可能会遇到一些需要进入“安全模式”来解决的问题。安全模式是一种特殊的启动选项,它以最小化配置启动操作系统,仅加载最基本的驱动程序和服务,从而帮助用户诊断和修复系统问题。本文中简鹿办公将详细…...
【CS61A 2024秋】Python入门课,全过程记录P7(Week13 Macros至完结)【完结撒花!】
文章目录 关于新的问题更好的解决方案Week13Mon Macros阅读材料Lab 11: Programs as Data, MacrosQ1: WWSD: QuasiquoteQ2: If ProgramQ3: Exponential PowersQ4: Repeat Wed SQL阅读材料Disc 11: MacrosQ1: Mystery MacroQ2: Multiple AssignmentQ3: Switch Optional Contest:…...
AspectJ 下 Advisor 的排序过程
在 AbstractAdvisorAutoProxyCreator#findEligibleAdvisors 方法中,找到 BeanFactory 中所有的 Advisor 后,针对当前 beanClass 进行过滤,筛选出符合当前 beanClass 的 Advisor,称之为 eligibleAdvisors。接着对 eligibleAdvisors…...
Unity 高度可扩展的技能与多 Buff 框架详解
一、框架设计 1.1 核心思想 组件化设计: 将技能和 Buff 抽象为可复用的组件,通过组合不同的组件实现复杂的效果。 数据驱动: 使用 ScriptableObject 或 JSON 等数据格式定义技能和 Buff 的属性,方便配置和修改。 事件驱动: 利用 Unity 的事件系统或自…...
机器学习中过拟合和欠拟合问题处理方法总结
目录 一、背景二、过拟合(Overfitting)2.1 基本概念2.2 过拟合4个最主要的特征2.3 防止过拟合的11个有效方法 三、欠拟合(Underfitting)3.1 基本概念3.2 欠拟合的4个特征3.3 防止欠拟合的11个有效方法 四、总结五、参考资料 一、背景 在机器学习模型训练…...
新一代高性能无线传输模块M-GATEWAY3
M-GATEWAY3是M3系列的通用接口模块,用于接收各种总线信号并将它们集成到一个系统中。该模块通过标准化传输协议XCPonETH进行输出,确保为各种测量应用提供无损信号。此外,M-GATEWAY3支持通过热点、ETH-PC或USB-C传输数据。借助M-GATEWAY3&…...
一、通义灵码插件保姆级教学-IDEA(安装篇)
JetBrains IDEA 中安装教学 第一步:事先准备 支持系统:Windows 7 ~ Windows 11、Linux、macOS;下载并安装兼容的 JetBrains IDEA 2020.3 及以上版本; 第二步:在 IntelliJ IDEA 中安装通义灵码 方法 1:通…...
【leetcode 32】1047. 删除字符串中的所有相邻重复项
Java中的queue、deque、ArrayDeque的区别 使用 Deque 作为堆栈(ArrayDeque是双端队列,当仅使用栈操作时push/pop,就是栈) class Solution {public String removeDuplicates(String s) {//使用 Deque 作为堆栈(ArrayDeque是双端队列,当仅使用栈…...
ubuntu 安装vnc之后,本地黑屏,vnc正常
ubuntu 安装vnc之后,本地黑屏,vnc正常 在Ubuntu系统中安装VNC服务器(如TightVNC或RealVNC)后,如果遇到连接时本地屏幕变黑的情况,可能是由于几种不同的配置或兼容性问题。以下是一些解决步骤,可以帮助你解决这个问题&…...
【实战AI】利用deepseek 在mac本地部署搭建个人知识库
之前的文章中实现了本地通过ollma 部署deepseek R1:14b 模型,这里我想继续实现个人知识库,方便自己文档,数据的检索; 下载anythingLLM 地址: https://anythingllm.com/desktop 下载安装即可;…...
ASP.NET Core的贫血模型与充血模型
目录 概念 需求 贫血模型 充血模型 总结 概念 贫血模型:一个类中只有属性或者成员变量,没有方法。充血模型:一个类中既有属性、成员变量,也有方法。 需求 定义一个类保存用户的用户名、密码、积分;用户必须具有…...
java基础6(黑马)
一、static 1.static修饰成员变量 static:叫静态,可以修饰成员变量、成员方法。 成员变量按照有无static,分两种。 类变量:有static修饰,属于类,在计算机中只有一份,会被类的全部对象共享。…...
LabVIEW外延片光致发光(PL)扫描系统
本文介绍了基于LabVIEW的PL扫描系统的开发过程,包括硬件选型(如ECOPIA激光器、EPP2000光谱仪)、软件架构(多线程控制、动态显示)、环境适配(温湿度控制、防震)等关键设计。结合工业需求…...
安装Jenkins
Linux中安装jenkins 采用RPM安装包方式:Jenkins安装包下载地址 wget https://pkg.jenkins.io/redhat-stable/jenkins-2.190.1-1.1.noarch.rpm执行安装 rpm -ivh jenkins-2.190.1-1.1.noarch.rpm修改配置文件: vi /etc/sysconfig/jenkins修改内容&…...
开发中常用的快捷键
开发中常用的快捷键 浏览器开发工具ideavscode 浏览器 清除浏览器的缓存:ctrl shift delete 开发工具 idea 前端JS代码格式化:ctrl alt L vscode...
前端如何判断浏览器 AdBlock/AdBlock Plus(最新版)广告屏蔽插件已开启拦截
2个月前AdBlock/AdBlock Plus疑似升级了一次 因为自己主要负责面对海外的用户项目,发现以前的检测AdBlock/AdBlock Plus开启状态方法已失效了,于是专门研究了一下。并尝试了很多方法。 已失效的老方法 // 定义一个检测 AdBlock 的函数 function chec…...
ASP.NET Core 如何使用 C# 向端点发出 POST 请求
使用 C#,将 JSON POST 到 REST API 端点;如何从 REST API 接收 JSON 数据。 本文需要 ASP .NET Core,并兼容 .NET Core 3.1、.NET 6和.NET 8。 要从端点获取数据,请参阅本文。 使用 . 将 JSON 数据发布到端点非常容易HttpClien…...
更新无忧:用 Docker 数据卷确保 Open WebUI 数据持久化
在使用 Docker 部署 Open WebUI 时,如何在更新容器的同时确保数据不丢失,始终是工程师们关注的焦点。每次拉取新版镜像、停止并重启容器时,如果没有正确挂载数据卷,配置和数据库数据极易流失,给生产环境带来不必要的麻…...
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_atomic_cmp_set 函数
目录 修正 执行 ./configure 命令时,输出: checking for OS Linux 6.8.0-52-generic x86_64 checking for C compiler ... found using GNU C compiler gcc version: 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) 所以当前环境是 x86_64 于是在 src…...
为什么我用Python控制仪器比C#慢很多?如何优化性能?
在自动化测试、实验室仪器控制等领域,Python、C# 和 C 是常见的编程语言选择。最近,我在使用 Python 控制仪器时,发现其交互速度明显比 C# 慢很多。这让我感到困惑,毕竟 Python 以其简洁和高效著称,为什么会出现这种情…...
Linux虚拟机克隆
克隆 从现有虚拟机(关机状态)克隆出新虚拟机,右键选择管理>克隆: 选择完整克隆 设置虚拟机名称及存储位置 开机修改系统相关配置 注意: 使用root 用户。 修改vim /etc/sysconfig/network-scripts/ifcfg-ens33 ,修改IP 地址 vim /etc/sysconfig…...
开发完的小程序如何分包
好几次了,终于想起来写个笔记记一下 我最开始并不会给小程序分包,然后我就各种搜,发现讲的基本上都是开发之前的小程序分包,可是我都开发完要发布了,提示我说主包太大需要分包,所以我就不会了。。。 好了…...
气体控制器联动风机,检测到环境出现异常时自动打开风机进行排风;
一、功能:检测到环境出现异常时自动打开风机进行排风; 二、设备: 1.气体控制器主机:温湿度,TVOC等探头的主机,可上报数据,探头监测到异常时,主机会监测到异常可联动风机或声光报警…...
攻防世界33 catcat-new【文件包含/flask_session伪造】
题目: 点击一只猫猫: 看这个url像是文件包含漏洞,试试 dirsearch扫出来/admin,访问也没成功(--delay 0.1 -t 5) 会的那几招全用不了了哈哈,那就继续看答案 先总结几个知识点 1./etc/passwd&am…...
让文物“活”起来,以3D数字化技术传承文物历史文化!
文物,作为不可再生的宝贵资源,其任何毁损都是无法逆转的损失。然而,当前文物保护与修复领域仍大量依赖传统技术,同时,文物管理机构和专业团队的力量相对薄弱,亟需引入数字化管理手段以应对挑战。 积木易搭…...
Java+vue前后端分离项目集群部署
一、项目概述 假设我们有一个前后端分离的项目,前端使用React或Vue框架,后端使用Spring Boot或Node.js。我们将分别部署前端和后端到集群环境中。 二、准备工作 1. 代码准备:确保前端和后端代码已经开发完成,并通过本地测试。 2…...
【算法解析】(2)分治算法:归并排序和快速排序
1. 分治算法(Divide and Conquer) 分治算法的核心思想是将一个大问题分解为多个小问题,分别解决这些小问题,然后将小问题的解合并起来得到大问题的解。 2. 算法步骤 分治算法通常包含以下三个步骤: 分解(Divide):将原问题分解为若干个规模较小、相互独立、与原问题…...
Qt文本处理【正则表达式】示例详解:【QRegularExpression】
在 Qt 中,正则表达式是处理文本的强大工具,它能够帮助我们匹配、搜索和替换特定的字符串模式。自 Qt 5 起,QRegularExpression 类提供了对 ECMAScript 标准的正则表达式支持,这使得它在处理各种复杂的字符串任务时变得更加高效和灵…...
在 Navicat 17 中扩展 PostgreSQL 数据类型 - 枚举类型
枚举类型 在 Navicat Premium 17 中创建 PostgreSQL 的自定义数据类型的系列中,我们已经探索了多个主题。在 第 1 部分 ,我们学习了如何为 免费 DVD 租赁数据库 创建自定义域。上周,我们创建了一个复合类型,用于从用户定义的函数…...
Spring Boot + MyBatis Field ‘xxx‘ doesn‘t have a default value 问题排查与解决
目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 执行代码的时候,出现某个字段无法添加 ### Error updating database. Cause: java.sql.SQLException: Field e_f_id doesnt have a default value ### The error may exist in cn...
python基础入门:6.2JSON与CSV数据处理
Python数据处理实战:JSON与CSV高效转换指南 # 天气数据转换示例 import json import csv from datetime import datetimedef process_weather_data(json_file, csv_file):"""将天气JSON数据转换为CSV格式"""with open(json_file, r,…...