线程相关面试题

news2025/6/6 5:48:52

提示:线程相关面试题,持续更新中

文章目录

  • 一、Java线程池
    • 1、Java线程池有哪些核心参数,分别有什么的作用?
    • 2、线程池有哪些拒绝策略?
    • 3、说一说线程池的执行流程?
    • 4、线程池核心线程数怎么设置呢?
    • 4、Java线程池中submit()和execute()方法有什么区别?
  • 二、ThreadLocal
    • 1、请介绍一下ThreadLocal底层是怎么实现的?
    • 2、ThreadLocal为什么会内存泄漏?
  • 三、Thread
    • 1、请说说sleep()和wait()有什么区别?
    • 2、多个线程如何保证按顺序执行?


一、Java线程池

1、Java线程池有哪些核心参数,分别有什么的作用?


ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        8,
        16,
        60,
        TimeUnit.SECONDS,
        new ArrayBlockingQueue<Runnable>(1024),
        Executors.defaultThreadFactory(),
        new ThreadPoolExecutor.CallerRunsPolicy()
);

构造方法最多的是7个参数:
	(1int corePoolSize : 线程池中的核心线程数量
		allowCoreThreadTimeOut:允许核心线程超时销毁,默认false(不销毁);
		boolean prestartCoreThread(),初始化一个核心线程;
		int prestartAllCoreThreads(),初始化所有核心线程;

	(2int maximumPoolSize : 线程池中允许的最大线程数
		当核心线程全部繁忙且任务队列存满之后,线程池会临时追加线程,直到总线程数达到maximumPoolSize这个上限;

	(3long keepAliveTime :线程空闲超时时间
		如果一个非核心线程处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁;

	(4TimeUnit unit :keepAliveTime的时间单位
 		(天、小时、分、秒......);

	(5BlockingQueue<Runnable> workQueue :任务队列
		当核心线程全部繁忙时,任务存放到该任务队列中,等待被核心线程来执行;

	(6ThreadFactory threadFactory :线程工厂
		用于创建线程,一般采用默认的线程工厂即可,也可以自定义实现;
		Executors.defaultThreadFactory():推荐使用,
		Executors.privilegedThreadFactory():已过时,不推荐使用,7RejectedExecutionHandler handler :拒绝策略(饱和策略)
		当任务太多来不及处理时,如何“拒绝”任务?
		
		“拒绝”触发条件:
			1、核心线程corePoolSize正在执行任务;
			2、线程池的任务队列workQueue已满;
			3、线程池中的线程数达到maximumPoolSize时;
			就需要“拒绝”掉新提交过来的任务;


2、线程池有哪些拒绝策略?


JDK提供了4种内置的拒绝策略:AbortPolicyCallerRunsPolicyDiscardOldestPolicyDiscardPolicy1AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常,这是默认的拒绝策略;
	2DiscardPolicy:直接丢弃任务,不抛出异常,没有任何提示;
	3DiscardOldestPolicy:丢弃任务队列中靠最前的任务,当前提交的任务不会丢弃;
	4CallerRunsPolicy: 交由任务的调用线程(提交任务的线程)来执行当前任务;

除了上面的四种拒绝策略,还可以通过实现RejectedExecutionHandler接口,实现自定义的拒绝策略;


3、说一说线程池的执行流程?


当提交一个新任务到线程池时,具体的执行流程如下: 
	1. 当我们提交任务,线程池会根据corePoolSize大小创建线程来执行任务; 
	2. 当任务的数量超过corePoolSize数量,后续的任务将会进入阻塞队列阻塞排队;
	3. 当阻塞队列也满了之后,那么将会继续创建(maximumPoolSize-corePoolSize)个数量的线程来执行任务,
	   如果任务处理完成,maximumPoolSize-corePoolSize个额外创建的线程等待 keepAliveTime之后被自动销毁;
	4. 如果达到maximumPoolSize,阻塞队列还是满的状态,那么将根据不同的拒绝策略进行拒绝处理; 

在这里插入图片描述


4、线程池核心线程数怎么设置呢?

在这里插入图片描述

	
Ncpu = cpu的核心数 ,Ucpu = cpu的使用率(在0~1之间)

W = 线程等待时间,C = 线程计算时间

举例:
8 * 100% * (1+60/40) = 20
8 * 100% * (1+80/20) = 40

----------------------------------------------------------------------------------------------------------------------------

任务分为CPU密集型和IO密集型 
	CPU密集型
		线程数 = CPU核心数 + 1; 
		
		这种任务主要是消耗CPU资源, 比如像加解密、压缩、计算等一系列需要大量耗费 CPU 资源的任务;
		+1,比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其它原因导致的任务暂停而带来的影响。
		一旦任务暂停,CPU 就会处于空闲状态,而在这种情况下多出来的一个线程就可以充分利用 CPU 的空闲时间; 

	IO密集型
		线程数 = CPU核心数 * 2;
		
		这种任务会有大部分时间在进行IO操作,比如像MySQL数据库、文件读写、网络通信等任务,这类任务不会特别消耗CPU资源,
		但是IO操作比较耗时,会占用比较多时间;
		线程在处理IO的时间段内不会占用CPU,这时就可以将CPU交出给其它线程使用,因此在IO密集型任务的应用中,可以多配置一些线程; 

----------------------------------------------------------------------------------------------------------------------------

基本原则:
	1、线程执行时间越多,就需要越少的线程;
	2、线程等待时间越多,就需要越多的线程;

以上理论参考依据,实际项目中建议在本地或者测试环境进行压测多次调整线程池大小,找到相对理想的值大小;


4、Java线程池中submit()和execute()方法有什么区别?


	1、 两个方法都可以向线程池提交任务;
	2、 execute只能提交Runnable,无返回值;
	3、 submit既可以提交Runnable,返回值为null,也可以提交Callable,返回值Future4execute()方法定义在Executor接口中;
	5submit()方法定义在ExecutorService接口中;
	6、 execute执行任务时遇到异常会直接抛出;
	7、 submit执行任务时遇到异常不会直接抛出,只有在调用Futureget()方法获取返回值时,才会抛出异常;

-----------------------------------------------------------------------------------------------------------------------

	RunnableCallable都是用于定义线程执行任务的接口
	
	特性						Runnable								Callable
	返回值						无(void)								有(泛型V)
	异常处理						不能抛出受检异常							可以抛出受检异常
	方法签名						void run()								V call() throws Exception
	使用场景						简单任务,无需结果						复杂任务,需要结果或异常处理
	线程池集成					execute(Runnable)						submit(Callable) + Future
	功能扩展性					基础									支持任务取消、超时、结果获取

	选择建议
		使用Runnable:当任务简单、无需返回值且不涉及受检异常时。
		使用Callable:当任务需要返回值、可能抛出异常或需要高级控制(如超时、取消)时。

在这里插入图片描述


二、ThreadLocal

1、请介绍一下ThreadLocal底层是怎么实现的?

在这里插入图片描述


定义:
	ThreadLocalJava 中用于实现线程隔离存储的核心工具类,它为每个线程提供独立的变量副本,确保线程间数据互不干扰。

-------------------------------------------------------------------------------------------------------------------------

	ThreadLocal是一个类似于HashMap的数据结构;
	
	ThreadLocal的实现原理就是通过set把value set到线程的threadlocals属性中,threadlocals是一个Map,
	其中的key是ThreadLocalthis引用,value是我们所set的值;

-------------------------------------------------------------------------------------------------------------------------

	解释:
		1、线程运行时,会生成ThreadLocalMap类型的名称为threadLocals的成员变量
		
		2ThreadLocalMap底层是Entry 数组
			键值对存储:Entry[] 数组存储键值对,键为 ThreadLocal 对象,值为线程本地变量。
			弱引用键:Entry 的键是弱引用(WeakReference<ThreadLocal<?>>),避免 ThreadLocal 实例无法被 GC 回收。
					但值仍为强引用,需手动清理。
	

2、ThreadLocal为什么会内存泄漏?


一、内存泄漏的核心原因
	1、弱引用键(Weak Key)的特性:
		ThreadLocalMapEntry 键是弱引用类型,指向 ThreadLocal 对象。
		弱引用的特点:当 ThreadLocal 实例没有其他强引用时,GC 会回收它,但 Entry 的值(Value)仍被强引用持有。
	2、值对象的强引用(Strong Value):
		Entry 的值是强引用,指向用户存储的对象。
		问题:即使 ThreadLocal 实例被 GC 回收,Entry 的值仍可能被线程长期持有(如线程池中的线程),导致值对象无法被释放。
		
二、内存泄漏的典型场景
	1、线程长期存活:
		 线程池场景:线程被复用(如 ExecutorService),且未调用 ThreadLocal.remove()。
		 后果:Entry 的值对象一直被线程持有,无法被 GC 回收。
	2、未调用 remove() 方法:
		 代码疏忽:在使用完 ThreadLocal 后,未显式调用 remove() 清理值。
		 后果:即使 ThreadLocal 实例被回收,值对象仍可能残留在 ThreadLocalMap 中。
		
三、内存泄漏的后果
	1、内存占用增长:值对象无法被释放,导致堆内存占用持续增加。
	2OOM 风险:在极端情况下,可能引发 OutOfMemoryErrorOOM)。
	
四、解决方案与最佳实践
	1、显式调用 remove():
		必须执行:在使用完 ThreadLocal 后,务必调用 remove() 清理值。
		示例:
			try {
			    threadLocal.set(value);
			    // ... 业务逻辑 ...
			} finally {
			    threadLocal.remove(); // 确保清理
			}
			
	2、避免静态 ThreadLocal 变量:
		风险:静态变量生命周期长,可能导致 ThreadLocalMap 长期存活。
		替代方案:使用局部变量或依赖注入框架管理。
		
	3、线程池场景的特殊处理:
		自定义线程池:在任务执行前后清理 ThreadLocal。
		使用 ThreadLocal 清理工具:如阿里开源的 TransmittableThreadLocal,支持线程池传递和清理。
		
	4、依赖 GC 的局限性:
		不要依赖 GC:虽然 ThreadLocalMap 在 set/get 操作时会扫描并清理部分过期 Entry(expungeStaleEntry),
					但这种清理是启发式的,无法保证完全释放。
					
五、底层机制补充
	1ThreadLocalMap 的清理逻辑:
		探测式清理:在 set/get 操作时,扫描 Entry 数组,发现键为 nullEntry,清除值并释放键。
		启发式清理:以对数复杂度清理部分过期数据,平衡性能与内存。
		
	2、为什么值不使用弱引用?
		设计权衡:若值也使用弱引用,可能导致用户无意识丢失数据。
		替代方案:通过 remove() 显式管理值的生命周期。


三、Thread


1、请说说sleep()和wait()有什么区别?


1. 所属类与方法签名
	sleep():
		属于Thread类。
		方法签名:public static void sleep(long millis) throws InterruptedException。
		是一个静态方法,作用于当前线程。
	wait():
		属于Object类。
		方法签名:public final void wait() throws InterruptedException(还有其他重载方法,如wait(long timeout))。
		是一个实例方法,必须通过对象调用。
		
2. 核心作用
	sleep():
		让当前线程暂停执行一段时间(以毫秒为单位)。
		不释放锁:线程在睡眠期间仍持有对象锁或监视器锁。
		用途:模拟延时、暂停线程执行(如轮询间隔、超时控制)。
	wait():
		让当前线程等待,释放对象锁,直到其他线程调用notify()notifyAll()。
		释放锁:线程在等待期间不再持有对象锁。
		用途:多线程间协调,等待某个条件满足(如生产者-消费者模型)。
		
3. 线程状态变化
	sleep():
		线程进入TIMED_WAITING状态。
		时间到后自动恢复执行。
	wait():
		线程进入WAITING(无超时)或TIMED_WAITING(有超时)状态。
		必须由其他线程调用notify()/notifyAll()(或超时)才能恢复。
		
4. 锁的行为
	sleep():
		不释放锁:即使线程睡眠,其他线程仍无法获取该线程持有的锁。
	wait():
		释放锁:线程释放对象锁,允许其他线程竞争锁并执行同步代码块。
		
5. 唤醒机制
	sleep():
		自动唤醒:睡眠时间到后,线程自动恢复执行。
	wait():
		被动唤醒:必须由其他线程调用notify()(唤醒单个等待线程)或notifyAll()(唤醒所有等待线程)。
		
6. 使用场景
	sleep():
		简单延时(如定时任务、超时重试)。
		示例:
			try {
			    Thread.sleep(1000); // 睡眠1秒
			} catch (InterruptedException e) {
			    e.printStackTrace();
			}
	wait():
		多线程协作(如生产者-消费者模型)。
		示例:
			synchronized (lock) {
			    while (!condition) {
			        lock.wait(); // 等待条件满足
			    }
			    // 执行操作
			}

特性sleep()wait()
所属类ThreadObject
释放锁
唤醒方式自动(时间到)被动(notify()/notifyAll())
线程状态TIMED_WAITINGWAITING/TIMED_WAITING
典型用途简单延时多线程协作
是否静态方法否(需通过对象调用)

2、多个线程如何保证按顺序执行?


比如任务B,它需要等待任务A执行之后才能执行,任务C需要等待任务B执行之后才能执行;

解决方法:
	1、通过join()方法使当前线程“阻塞”,等待指定线程执行完毕后继续执行;
	2、通过创建单一化线程池newSingleThreadExecutor()实现;
	3、通过倒数计时器CountDownLatch实现;
	4、使用Object的wait/notify方法实现;
	5、使用线程的Condition(条件变量)方法实现;
	6、使用线程的CyclicBarrier(回环栅栏)方法实现;
	7、使用线程的Semaphore(信号量)方法实现;


(1) 通过join()方法使当前线程“阻塞”,等待指定线程执行完毕后继续执行:


方法1public static void main(String[] args) throws Exception {
	        // t1线程
	        Thread t1 = new Thread(() -> {
	            System.out.println(Thread.currentThread().getName() + " 执行");
	        }, "t1");
	
	        // t2线程
	        Thread t2 = new Thread(() -> {
	           try {
	                t1.join();
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	            System.out.println(Thread.currentThread().getName() + " 执行");
	        }, "t2");
	
	        // t3线程
	        Thread t3 = new Thread(() -> {
	            try {
	                t2.join();
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	            System.out.println(Thread.currentThread().getName() + " 执行");
	        }, "t3");

	        t1.start();
	        t2.start();
	        t3.start();
	    }

---------------------------------------------------------------------------------------------------------------------------
方法2public static void main(String[] args) throws Exception {
	
	        // t1线程
	        Thread t1 = new Thread(() -> {
	            System.out.println(Thread.currentThread().getName() + " 执行");
	        }, "t1");
	
	        // t2线程
	        Thread t2 = new Thread(() -> {
	            System.out.println(Thread.currentThread().getName() + " 执行");
	        }, "t2");
	
	        // t3线程
	        Thread t3 = new Thread(() -> {
	            System.out.println(Thread.currentThread().getName() + " 执行");
	        }, "t3");
	
	        t1.start();
	        t1.join();
	
	        t2.start();
	        t2.join();
	
	        t3.start();
	    }

(2) 通过创建单一化线程池newSingleThreadExecutor()实现:

public class Test {

	//自己手动创建单一化线程池(推荐使用)
    private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
            1,
            0L,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1024),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.DiscardOldestPolicy());

	//创建单一化线程池(不建议使用Executors)
    private static ExecutorService executorService = Executors.newSingleThreadExecutor();

    public static void main(String[] args) throws Exception {

        // t1线程
        Thread t1 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " t1执行");
        }, "t1");

        // t2线程
        Thread t2 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " t2执行");
        }, "t2");

        // t3线程
        Thread t3 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " t3执行");
        }, "t3");

        threadPoolExecutor.execute(t1);
        threadPoolExecutor.execute(t2);
        threadPoolExecutor.execute(t3);

        threadPoolExecutor.shutdown();
    }
}

(3) 通过倒数计时器CountDownLatch实现:

public class Test {

    /** 用于判断t1线程是否执行,倒计时设置为1,执行后减1 */
    private static final CountDownLatch countDownLatch1 = new CountDownLatch(1);

    /** 用于判断t2线程是否执行,倒计时设置为1,执行后减1 */
    private static final CountDownLatch countDownLatch2 = new CountDownLatch(1);

    public static void main(String[] args) throws Exception {

        // t1线程
        Thread t1 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " 执行");
            countDownLatch1.countDown(); // -1
        }, "t1");

        // t2线程
        Thread t2 = new Thread(() -> {
            try {
                countDownLatch1.await(); //只有当 countDownLatch1 的计数器归零后,才会继续执行后续代码
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 执行");
            countDownLatch2.countDown();
        }, "t2");

        // t3线程
        Thread t3 = new Thread(() -> {
            try {
                countDownLatch2.await(); //只有当 countDownLatch2 的计数器归零后,才会继续执行后续代码
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 执行");
        }, "t3");

        t1.start();
        t2.start();
        t3.start();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2398616.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pikachu通关教程-目录遍历漏洞(../../)

目录遍历漏洞也可以叫做信息泄露漏洞、非授权文件包含漏洞等. 原理:目录遍历漏洞的原理比较简单&#xff0c;就是程序在实现上没有充分过滤用户输入的../之类的目录跳转符&#xff0c;导致恶意用户可以通过提交目录跳转来遍历服务器上的任意文件。 这里的目录跳转符可以是../…

Maven-生命周期

目录 1.项目对象模型 2.依赖管理模型 3.仓库&#xff1a;用于存储资源&#xff0c;管理各种jar包 4.本地仓库路径 1.项目对象模型 2.依赖管理模型 3.仓库&#xff1a;用于存储资源&#xff0c;管理各种jar包 4.本地仓库路径

Matlab实现LSTM-SVM回归预测,作者:机器学习之心

Matlab实现LSTM-SVM回归预测&#xff0c;作者&#xff1a;机器学习之心 目录 Matlab实现LSTM-SVM回归预测&#xff0c;作者&#xff1a;机器学习之心效果一览基本介绍程序设计参考资料 效果一览 基本介绍 代码主要功能 该代码实现了一个LSTM-SVM回归预测模型&#xff0c;核心流…

Spring Boot 自动配置原理:从入门到精通

Spring Boot 的自动配置是其核心特性之一&#xff0c;它极大地简化了 Spring 应用的开发&#xff0c;让开发者可以专注于业务逻辑&#xff0c;而无需编写大量的配置代码。 本文将深入探讨 Spring Boot 自动配置的原理&#xff0c;帮助你理解其工作机制&#xff0c;并能灵活运用…

腾讯 ovCompose 开源,Kuikly 鸿蒙和 Compose DSL 开源,腾讯的“双”鸿蒙方案发布

近日&#xff0c;腾讯的 ovCompose 和 Kuikly 都发布了全新开源更新&#xff0c;其中 Kuikly 在之前我们聊过&#xff0c;本次 Kuikly 主要是正式开源鸿蒙支持部分和 Compose DSL 的相关支持&#xff0c;而 ovCompose 是腾讯视频团队基于 Compose Multiplatform 生态推出的跨平…

PYTHON调用讯飞C/C++动态库实现离线语音合成并且实时播放

语音合成(Text-to-Speech, TTS)技术在现代应用中扮演着越来越重要的角色&#xff0c;从智能客服到有声读物&#xff0c;从导航系统到辅助工具&#xff0c;TTS技术无处不在。本文将详细介绍如何使用Python结合科大讯飞的离线SDK实现一个本地化的语音合成系统。 技术背景 离线语…

黑马Java面试笔记之 消息中间件篇(RabbitMQ)

一. 消息丢失问题 RabbitMQ如何保证消息不丢失&#xff1f; 使用场景有&#xff1a; 异步发送&#xff08;验证码、短信、邮件... &#xff09;MYSQL和Redis&#xff0c;ES之间的数据同步分布式事务削峰填谷...... 消息丢失原因会有三种情况&#xff0c;分别分析一下 1.1 生…

Redisson学习专栏(五):源码阅读及Redisson的Netty通信层设计

文章目录 前言一、分布式锁核心实现&#xff1a;RedissonLock源码深度解析1.1 加锁机制&#xff1a;原子性与重入性实现1.2 看门狗机制&#xff1a;锁自动续期设计1.3 解锁机制&#xff1a;安全释放与通知1.4 锁竞争处理&#xff1a;等待队列与公平性1.5 容错机制&#xff1a;异…

结合 AI 生成 mermaid、plantuml 等图表

AI 画图 AI 画图并不是真的让 AI 画一个图片&#xff0c;而是让 AI 根据你的需求&#xff0c;生成对应的需求文本&#xff0c;再根据 “文本画图” 来生成图片。 Mermaid mermaid 支持流程图、时序图、架构图等等多种图片绘制。当然最终生成的效果和样式会根据不同的“文本代…

R语言使用随机过采样(Random Oversampling)平衡数据集

随机过采样&#xff08;Random Oversampling&#xff09;是一种用于平衡数据集的技术&#xff0c;常用于机器学习中处理类别不平衡问题。当某个类别的样本数量远少于其他类别时&#xff08;例如二分类中的正负样本比例悬殊&#xff09;&#xff0c;模型可能会偏向多数类&#x…

【Kotlin】高阶函数Lambda内联函数

【Kotlin】简介&变量&类&接口 【Kotlin】数字&字符串&数组&集合 【Kotlin】高阶函数&Lambda&内联函数 【Kotlin】表达式&关键字 文章目录 函数还是属性高阶函数抽象和高阶函数实例&#xff1a; 函数作为参数的需求方法引用表达式更多使用场…

从0开始学vue:vue3和vue2的关系

一、版本演进关系1. 继承关系2. 版本生命周期 二、核心差异对比三、关键演进方向1. Composition API2. 性能优化 四、迁移策略1. 兼容构建模式2. 关键破坏性变更 五、生态演进1. 官方库升级2. 构建工具链 六、选型建议1. 新项目2. 现有项目 七、未来展望 一、版本演进关系 1. …

MySQL关系型数据库学习

学习参考链接&#xff1a;https://www.runoob.com/mysql/mysql-tutorial.html Windows 安装MYSQL服务端的步骤&#xff1a;https://www.runoob.com/w3cnote/windows10-mysql-installer.html 1. 概念学习 MySQL 是一种关联数据库管理系统&#xff0c;关联数据库将数据保存在不…

嵌入式硬件篇---龙芯2k1000串口

针对串口错误 “device reports readiness to read but returned no data (Device disconnected or multiple access on port?)” 的排查和解决方法 硬件方面 检查连接 确认串口设备&#xff08;如串口线、连接的模块等&#xff09;与龙芯设备之间的物理连接是否牢固&#xf…

谷歌地图苹果版v6.138.2 - 前端工具导航

谷歌地图(Google maps)苹果版是是由谷歌官方推出的一款手机地图应用。软件功能强大&#xff0c;支持本地搜索查找世界各地的地址、地点和商家&#xff1b;支持在街景视图中查看世界各地的360度全景图&#xff1b;支持查找乘坐火车、公交车和地铁的路线&#xff0c;或者查找步行…

NSSCTF [LitCTF 2025]test_your_nc

[复现]绕过学的还是太差了&#xff0c;多积累吧 ​​​​​​题目 题目: 给了一个python文件 #!/bin/python3 import osprint("input your command")blacklist [cat,ls, ,cd,echo,<,${IFS},sh,\\]while True:command input()for i in blacklist:if i in com…

Qwen3高效微调

高效微调 场景、模型、数据、算力 高效微调的应用场景 对话风格微调&#xff1a;高效微调可以用于根据特定需求调整模型的对话风格。例如&#xff0c;针对客服系统、虚拟助理等场景&#xff0c;模型可以通过微调来适应不同的 语气、礼貌程度 或 回答方式&#xff0c;从而在与…

Gitee Wiki:重塑关键领域软件研发的知识管理范式

在数字化转型浪潮席卷全球的当下&#xff0c;关键领域软件研发正面临前所未有的知识管理挑战。传统文档管理模式的局限性日益凸显&#xff0c;知识传承的断层问题愈发严重&#xff0c;团队协作效率的瓶颈亟待突破。Gitee Wiki作为新一代知识管理平台&#xff0c;正在通过技术创…

redis的哨兵模式和Redis cluster

目录 一. redis的主从复制 二. 哨兵模式 2.1 定义 2.2 作用 2.3 配置实例 三. Redis cluster 3.1 定义 3.2 作用 3.3 配置实例 1. 新建集群文件目录 2. 准备可执行文件到每个文件夹 3. 开启群集功能 4. 启动redis节点 5. 查看是否启动成功 6. 启动集群 7. 测试…

农业机器人的开发

农业机器人的开发 喷农药机器人 番茄采摘机器人 葡萄采摘机器人 黄瓜采摘机器人 西瓜采摘机器人 蘑菇采摘机器人 草莓采摘机器人 草莓采摘机器人综述 视觉系统 CCD摄像机&#xff0c;距离传感器&#xff0c;PC计算机 其中CCD摄像机的作用是进行彩色图像的采集和进行果…