Java 线程池:深入理解与高效应用
在 Java 并发编程中,线程池是一种非常重要的技术。它可以有效地管理和复用线程,提高系统的性能和资源利用率。本文将深入探讨 Java 线程池的概念、原理、使用方法以及最佳实践,帮助读者更好地理解和应用线程池。
一、引言
在现代软件开发中,多线程编程是提高程序性能和响应性的重要手段。然而,直接创建和管理线程会带来一些问题,如线程创建和销毁的开销、资源浪费、线程过多导致的系统性能下降等。为了解决这些问题,Java 提供了线程池技术。线程池可以预先创建一定数量的线程,当有任务需要执行时,从线程池中获取一个空闲线程来执行任务,任务完成后,线程不会被立即销毁,而是返回线程池等待下一个任务。这样可以避免频繁地创建和销毁线程,提高系统的性能和资源利用率。
二、线程池的概念与原理
(一)线程池的基本概念
线程池是一种管理线程的工具,它包含了一组预先创建的线程和一个任务队列。当有任务需要执行时,将任务提交到任务队列中,线程池中的线程会从任务队列中获取任务并执行。如果任务队列中没有任务,线程会进入等待状态,直到有新的任务到来。当线程执行完一个任务后,它会继续从任务队列中获取下一个任务,或者进入等待状态,等待新的任务到来。
(二)线程池的工作原理
- 线程池的创建
- 在创建线程池时,可以指定线程池的核心线程数量、最大线程数量、任务队列的类型和大小等参数。核心线程数量是指线程池中始终保持运行的线程数量,即使这些线程处于空闲状态。最大线程数量是指线程池中允许的最大线程数量,当任务队列已满且核心线程都在忙碌时,线程池会创建新的线程来执行任务,直到线程数量达到最大线程数量。
- 任务的提交
- 当有任务需要执行时,可以通过线程池的
execute方法或submit方法将任务提交到线程池中。execute方法用于提交一个Runnable任务,没有返回值;submit方法用于提交一个Callable任务,有返回值。提交任务后,线程池会根据当前的线程状态和任务队列的情况来决定如何执行任务。
- 当有任务需要执行时,可以通过线程池的
- 线程的执行
- 线程池中的线程会从任务队列中获取任务并执行。如果任务队列中没有任务,线程会进入等待状态,直到有新的任务到来。当线程执行完一个任务后,它会继续从任务队列中获取下一个任务,或者进入等待状态,等待新的任务到来。如果线程在执行任务过程中发生异常,线程池会创建一个新的线程来替代它,并继续执行任务。
- 线程池的关闭
- 当不再需要线程池时,可以通过线程池的
shutdown方法或shutdownNow方法来关闭线程池。shutdown方法会等待线程池中所有的任务执行完毕后再关闭线程池;shutdownNow方法会立即停止线程池的执行,并尝试中断正在执行任务的线程,返回尚未执行的任务列表。
- 当不再需要线程池时,可以通过线程池的
三、Java 线程池的类型与创建
(一)Java 中的线程池类型
FixedThreadPool(固定大小线程池)FixedThreadPool是一种固定大小的线程池,它在创建时指定了线程池的核心线程数量和最大线程数量,并且这两个数量是相等的。当有任务提交到线程池中时,如果线程池中存在空闲线程,就会立即执行任务;如果线程池中没有空闲线程,就会将任务加入到任务队列中等待执行。- 特点:线程数量固定,不会因为任务的增加而创建新的线程,也不会因为任务的减少而销毁线程。适用于需要限制线程数量的场景,如服务器端的连接处理。
CachedThreadPool(可缓存线程池)CachedThreadPool是一种可缓存的线程池,它在创建时没有指定线程池的核心线程数量和最大线程数量。当有任务提交到线程池中时,如果线程池中存在空闲线程,就会立即执行任务;如果线程池中没有空闲线程,就会创建一个新的线程来执行任务。当线程在一段时间内没有执行任务时,就会被回收。- 特点:线程数量不固定,可以根据任务的数量自动调整线程数量。适用于执行大量短期任务的场景,如网页爬虫。
ScheduledThreadPool(定时任务线程池)ScheduledThreadPool是一种用于执行定时任务的线程池,它在创建时指定了线程池的核心线程数量。当有定时任务提交到线程池中时,线程池会创建一个新的线程来执行任务,并在任务执行完毕后将线程回收。如果在任务执行过程中发生异常,线程池会创建一个新的线程来替代它,并继续执行任务。- 特点:可以执行定时任务和周期性任务。适用于需要定期执行任务的场景,如定时备份数据。
SingleThreadExecutor(单线程线程池)SingleThreadExecutor是一种单线程的线程池,它在创建时只有一个核心线程。当有任务提交到线程池中时,这个核心线程会执行任务。如果任务在执行过程中发生异常,线程池会创建一个新的线程来替代它,并继续执行任务。- 特点:只有一个线程在执行任务,保证任务按照提交的顺序依次执行。适用于需要保证任务顺序执行的场景,如日志记录。
(二)创建线程池的方法
- 使用
Executors工厂类创建线程池- Java 提供了
Executors工厂类来方便地创建不同类型的线程池。可以使用Executors.newFixedThreadPool、Executors.newCachedThreadPool、Executors.newScheduledThreadPool和Executors.newSingleThreadExecutor方法分别创建固定大小线程池、可缓存线程池、定时任务线程池和单线程线程池。 - 示例代码:
- Java 提供了
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {// 创建固定大小线程池ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);// 创建可缓存线程池ExecutorService cachedThreadPool = Executors.newCachedThreadPool();// 创建定时任务线程池ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);// 创建单线程线程池ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();}
}
- 使用
ThreadPoolExecutor构造函数创建线程池- 除了使用
Executors工厂类创建线程池外,还可以直接使用ThreadPoolExecutor构造函数来创建线程池。这样可以更加灵活地控制线程池的参数,如核心线程数量、最大线程数量、任务队列的类型和大小等。 - 示例代码:
- 除了使用
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class CustomThreadPoolExample {public static void main(String[] args) {// 创建线程池,核心线程数量为 3,最大线程数量为 5,任务队列大小为 10,任务超时时间为 1 分钟ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3,5,1,TimeUnit.MINUTES,new ArrayBlockingQueue<>(10));}
}
四、线程池的任务提交与执行
(一)提交任务的方法
execute方法execute方法用于提交一个Runnable任务到线程池中执行,没有返回值。如果线程池中的线程数量小于核心线程数量,就会创建一个新的线程来执行任务;如果线程池中的线程数量等于核心线程数量,就会将任务加入到任务队列中等待执行。- 示例代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ExecuteExample {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(3);executorService.execute(() -> {System.out.println("Task executed by thread: " + Thread.currentThread().getName());});executorService.shutdown();}
}
submit方法submit方法用于提交一个Callable任务到线程池中执行,有返回值。如果线程池中的线程数量小于核心线程数量,就会创建一个新的线程来执行任务;如果线程池中的线程数量等于核心线程数量,就会将任务加入到任务队列中等待执行。当任务执行完毕后,会返回一个Future对象,可以通过这个对象来获取任务的执行结果。- 示例代码:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;public class SubmitExample {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(3);Future<Integer> future = executorService.submit(() -> {System.out.println("Task executed by thread: " + Thread.currentThread().getName());return 42;});try {Integer result = future.get();System.out.println("Task result: " + result);} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}executorService.shutdown();}
}
(二)任务的执行过程
- 线程从任务队列中获取任务
- 线程池中的线程会不断地从任务队列中获取任务并执行。如果任务队列中没有任务,线程会进入等待状态,直到有新的任务到来。当有任务提交到线程池中时,线程池会根据当前的线程状态和任务队列的情况来决定如何执行任务。
- 任务的执行
- 线程获取到任务后,会执行任务中的代码。如果任务在执行过程中发生异常,线程池会创建一个新的线程来替代它,并继续执行任务。如果任务执行成功,线程会继续从任务队列中获取下一个任务,或者进入等待状态,等待新的任务到来。
- 任务的返回结果
- 如果提交的任务是一个
Callable任务,并且使用了submit方法提交任务,那么可以通过Future对象来获取任务的返回结果。如果任务在执行过程中发生异常,Future对象的get方法会抛出相应的异常。
- 如果提交的任务是一个
五、线程池的参数调整与性能优化
(一)线程池参数的含义与调整方法
- 核心线程数量(corePoolSize)
- 核心线程数量是指线程池中始终保持运行的线程数量,即使这些线程处于空闲状态。当有任务提交到线程池中时,如果线程池中存在空闲线程,就会立即执行任务;如果线程池中没有空闲线程,就会将任务加入到任务队列中等待执行。如果任务队列已满且核心线程都在忙碌时,线程池会创建新的线程来执行任务,直到线程数量达到最大线程数量。
- 调整方法:根据任务的类型和数量来调整核心线程数量。如果任务是 CPU 密集型的,即任务主要消耗 CPU 资源,可以将核心线程数量设置为与 CPU 核心数量相等或稍大一些,以充分利用 CPU 资源。如果任务是 I/O 密集型的,即任务主要消耗 I/O 资源,可以将核心线程数量设置得较大一些,以提高线程的并发度。
- 最大线程数量(maximumPoolSize)
- 最大线程数量是指线程池中允许的最大线程数量。当任务队列已满且核心线程都在忙碌时,线程池会创建新的线程来执行任务,直到线程数量达到最大线程数量。如果任务队列已满且线程数量达到最大线程数量,那么新提交的任务将被拒绝执行。
- 调整方法:根据系统的资源情况和任务的类型来调整最大线程数量。如果系统的资源比较充足,可以将最大线程数量设置得较大一些,以提高线程的并发度。如果系统的资源比较紧张,可以将最大线程数量设置得较小一些,以避免系统资源的过度消耗。
- 任务队列(workQueue)
- 任务队列是用于存储等待执行的任务的队列。当有任务提交到线程池中时,如果线程池中存在空闲线程,就会立即执行任务;如果线程池中没有空闲线程,就会将任务加入到任务队列中等待执行。
- 调整方法:根据任务的类型和数量来选择合适的任务队列类型和大小。如果任务是 CPU 密集型的,可以选择一个较小的任务队列,以避免任务在队列中等待时间过长。如果任务是 I/O 密集型的,可以选择一个较大的任务队列,以提高线程的并发度。常见的任务队列类型有
ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等。
- 线程空闲时间(keepAliveTime)
- 线程空闲时间是指线程在没有任务可执行时的最大等待时间。当线程在一段时间内没有执行任务时,就会被回收。如果线程空闲时间设置得过长,可能会导致线程资源的浪费;如果线程空闲时间设置得过短,可能会导致线程频繁地创建和销毁,增加系统的开销。
- 调整方法:根据任务的类型和数量来调整线程空闲时间。如果任务是短期任务,可以将线程空闲时间设置得较短一些,以避免线程资源的浪费。如果任务是长期任务,可以将线程空闲时间设置得较长一些,以减少线程的创建和销毁次数。
- 拒绝策略(rejectedExecutionHandler)
- 拒绝策略是指当任务队列已满且线程数量达到最大线程数量时,新提交的任务将被拒绝执行时采取的策略。Java 提供了四种拒绝策略,分别是
AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy和DiscardPolicy。 - 调整方法:根据系统的需求和任务的重要性来选择合适的拒绝策略。如果任务比较重要,可以选择
CallerRunsPolicy,让提交任务的线程自己执行任务;如果任务不太重要,可以选择DiscardPolicy或DiscardOldestPolicy,直接丢弃新提交的任务。
- 拒绝策略是指当任务队列已满且线程数量达到最大线程数量时,新提交的任务将被拒绝执行时采取的策略。Java 提供了四种拒绝策略,分别是
(二)性能优化的技巧与注意事项
- 合理设置线程池参数
- 根据任务的类型和数量来合理设置线程池的参数,如核心线程数量、最大线程数量、任务队列的类型和大小等。避免设置过大或过小的参数,以免影响系统的性能和资源利用率。
- 避免任务阻塞
- 在任务执行过程中,尽量避免任务的阻塞,如 I/O 操作、数据库访问等。可以使用异步 I/O、连接池等技术来减少任务的阻塞时间,提高线程的并发度。
- 监控线程池状态
- 可以使用 Java 的监控工具,如
jconsole、VisualVM等,来监控线程池的状态,如线程数量、任务队列大小、任务执行时间等。根据监控结果来调整线程池的参数,以提高系统的性能和资源利用率。
- 可以使用 Java 的监控工具,如
- 避免线程泄漏
- 在任务执行过程中,要注意避免线程泄漏。线程泄漏是指线程在执行任务过程中,由于某些原因没有正确地释放资源,导致线程一直处于运行状态,无法被回收。可以使用
try-with-resources语句、finally块等方式来确保资源的正确释放。
- 在任务执行过程中,要注意避免线程泄漏。线程泄漏是指线程在执行任务过程中,由于某些原因没有正确地释放资源,导致线程一直处于运行状态,无法被回收。可以使用
- 考虑任务的优先级
- 如果任务有不同的优先级,可以考虑使用优先级队列来存储任务,以便高优先级的任务能够优先执行。Java 提供了
PriorityBlockingQueue类来实现优先级队列。
- 如果任务有不同的优先级,可以考虑使用优先级队列来存储任务,以便高优先级的任务能够优先执行。Java 提供了
六、线程池的应用场景与实际案例
(一)应用场景
- 网络服务器
- 在网络服务器中,需要同时处理多个客户端的连接请求。可以使用线程池来管理连接处理线程,提高服务器的并发处理能力。当有新的连接请求到来时,从线程池中获取一个空闲线程来处理连接,连接处理完毕后,线程返回线程池等待下一个连接请求。
- 数据库连接池
- 在数据库访问中,频繁地创建和销毁数据库连接会带来很大的开销。可以使用线程池来管理数据库连接,提高数据库访问的效率。当有数据库访问请求到来时,从线程池中获取一个数据库连接来执行查询操作,查询完毕后,将数据库连接返回线程池等待下一个查询请求。
- 任务调度
- 在任务调度中,需要定期执行一些任务。可以使用定时任务线程池来管理任务执行线程,提高任务调度的效率。当有定时任务需要执行时,从线程池中获取一个空闲线程来执行任务,任务执行完毕后,线程返回线程池等待下一个定时任务。
- 并行计算
- 在并行计算中,需要同时执行多个计算任务。可以使用线程池来管理计算任务执行线程,提高并行计算的效率。将计算任务分解为多个子任务,提交到线程池中执行,最后将子任务的结果合并得到最终的计算结果。
(二)实际案例
- 网络服务器案例
- 假设我们要开发一个简单的网络服务器,能够同时处理多个客户端的连接请求。可以使用线程池来管理连接处理线程,提高服务器的并发处理能力。
- 示例代码:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class NetworkServerExample {public static void main(String[] args) {try {// 创建服务器套接字,监听端口 8080ServerSocket serverSocket = new ServerSocket(8080);System.out.println("服务器启动,监听端口 8080");// 创建线程池,核心线程数量为 5,最大线程数量为 10ExecutorService executorService = Executors.newFixedThreadPool(5);while (true) {// 等待客户端连接Socket clientSocket = serverSocket.accept();System.out.println("客户端连接:" + clientSocket.getInetAddress());// 将客户端连接处理任务提交到线程池executorService.execute(() -> handleClient(clientSocket));}} catch (IOException e) {e.printStackTrace();}}private static void handleClient(Socket clientSocket) {try {// 读取客户端发送的数据java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(clientSocket.getInputStream()));String request = in.readLine();System.out.println("收到客户端请求:" + request);// 处理请求并发送响应java.io.PrintWriter out = new java.io.PrintWriter(clientSocket.getOutputStream(), true);out.println("HTTP/1.1 200 OK");out.println("Content-Type: text/html");out.println();out.println("<html><body>Hello, World!</body></html>");// 关闭客户端连接clientSocket.close();} catch (IOException e) {e.printStackTrace();}}
}
- 数据库连接池案例
- 在数据库访问中,频繁地创建和销毁数据库连接会带来很大的开销。可以使用线程池来管理数据库连接,提高数据库访问的效率。
- 示例代码:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;public class DatabaseConnectionPool {private static final int POOL_SIZE = 10;private BlockingQueue<Connection> connectionQueue;public DatabaseConnectionPool() {try {Class.forName("com.mysql.jdbc.Driver");connectionQueue = new LinkedBlockingQueue<>(POOL_SIZE);for (int i = 0; i < POOL_SIZE; i++) {Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password");connectionQueue.add(connection);}} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();}}public Connection getConnection() throws InterruptedException {return connectionQueue.take();}public void releaseConnection(Connection connection) {connectionQueue.add(connection);}
}
- 任务调度案例
- 在任务调度中,需要定期执行一些任务。可以使用定时任务线程池来管理任务执行线程,提高任务调度的效率。
- 示例代码:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class TaskSchedulerExample {public static void main(String[] args) {ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3);// 每隔 5 秒执行一次任务scheduler.scheduleAtFixedRate(() -> {System.out.println("执行定时任务:" + System.currentTimeMillis());}, 0, 5, TimeUnit.SECONDS);}
}
- 并行计算案例
- 在并行计算中,需要同时执行多个计算任务。可以使用线程池来管理计算任务执行线程,提高并行计算的效率。
- 示例代码:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;public class ParallelComputingExample {public static void main(String[] args) {List<Integer> numbers = new ArrayList<>();for (int i = 0; i < 100; i++) {numbers.add(i);}ExecutorService executorService = Executors.newFixedThreadPool(5);List<Future<Integer>> futures = new ArrayList<>();for (Integer number : numbers) {Callable<Integer> task = () -> {return number * number;};futures.add(executorService.submit(task));}int sum = 0;for (Future<Integer> future : futures) {try {sum += future.get();} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}}System.out.println("并行计算结果:" + sum);executorService.shutdown();}
}
七、结论
Java 线程池是一种非常强大的并发编程工具,它可以有效地管理和复用线程,提高系统的性能和资源利用率。在实际应用中,我们可以根据任务的类型和数量来选择合适的线程池类型,并合理调整线程池的参数,以达到最佳的性能效果。同时,我们还需要注意避免线程泄漏、任务阻塞等问题,确保线程池的稳定运行。通过合理地使用线程池,我们可以轻松地实现高并发、高性能的 Java 应用程序。
相关文章:
Java 线程池:深入理解与高效应用
在 Java 并发编程中,线程池是一种非常重要的技术。它可以有效地管理和复用线程,提高系统的性能和资源利用率。本文将深入探讨 Java 线程池的概念、原理、使用方法以及最佳实践,帮助读者更好地理解和应用线程池。 一、引言 在现代软件开发中&a…...
week08 zookeeper多种安装与pandas数据变换操作-new
课程1-hadoop-Zookeeper安装 Ububtu18.04安装Zookeeper3.7.1 环境与版本 这里采用的ubuntu18.04环境的基本配置为: hostname 为master 用户名为hadoop 静态IP为 192.168.100.3 网关为 192.168.100.2 防火墙已经关闭 /etc/hosts已经配置全版本下载地址࿱…...
js构造函数和原型对象,ES6中的class,四种继承方式
一、构造函数 1.构造函数是一种特殊的函数,主要用来初始化对象 2.使用场景 常见的{...}语法允许创建一个对象。可以通过构造函数来快速创建多个类似的对象。 const Peppa {name: 佩奇,age: 6,sex: 女}const George {name: 乔治,age: 3,sex: 男}const Mum {nam…...
电脑连接海康相机并在PictureBox和HWindowControl中分别显示。
展示结果: 下面附上界面中所有控件的Name,只需照着红字设置对应的控件Name即可 下面附上小编主界面的全部代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; …...
直播系统源码技术搭建部署流程及配置步骤
系统环境要求 PHP版本:5.6、7.3 Mysql版本:5.6,5.7需要关闭严格模式 Nginx:任何版本 Redis:需要给所有PHP版本安装Redis扩展,不需要设置Redis密码 最好使用面板安装:宝塔面板 - 简单好用的…...
Spring+ActiveMQ
1. 环境搭建 1.1 env-version JDK 1.8 Spring 2.7.13 Maven 3.6 ActiveMQ 5.15.2 1.2 docker-compose.yml version: 3.8services:activemq:image: rmohr/activemq:5.16.3container_name: activemqports:- "61616:61616"- "8161:8161"environment…...
Linux 常用命令总汇
查询所有wifi nmcli dev wifi list 链接wifi sudo nmcli dev wifi connect XXXX password XXXX 查询本机IP ifconfig 查询联网情况 ping www.baidu.com 进入.bash gedit ~/.bashrc sudo dpkg -i XXX.deb 安装超级终端 sudo apt install terminator 超级终端常用…...
fmql之Linux RTC
模拟i2c,连接rtc芯片。 dts: /{ // 根节点i2c_gpio: i2c-gpio {#address-cells <1>;#size-cells <0>;compatible "i2c-gpio";// MIO56-SDA, MIO55-SCL // 引脚编号gpios <&portc 2 0&portc 1 0 >;i2c-gp…...
Flask-SocketIO 简单示例
用于服务端和客户端通信,服务端主动给客户端发送消息 前提: 确保安装了socket库: pip install flask-socketio python-socketio服务端代码 from flask import Flask from flask_socketio import SocketIO import threading import timeap…...
Vue 3 的组件式开发(2)
1 Vue 3 组件的插槽 插槽(Slot)是Vue组件中的一个重要概念,它允许父组件向子组件中插入HTML结构或其他组件,从而实现内容的自定义和复用。以下是对Vue 3组件插槽的详细讲解: 1.1 插槽的基本概念 插槽可以被视为子组…...
python 爬虫 入门 四、线程,进程,协程
目录 一、进程 特征: 使用: 初始代码 进程改装代码 二、线程 特征: 使用: 三、协程 后续:五、抓取图片、视频 线程和进程大部分人估计都知道,但协程就不一定了。 一、进程 进程是操作系统分配资…...
cloak斗篷伪装下的独立站
随着互联网的不断进步,越来越多的跨境电商卖家开始认识到独立站的重要性,并纷纷建立自己的独立站点。对于那些有志于进入这一领域的卖家来说,独立站是什么呢?独立站是指个人或小型团队自行搭建和运营的网站。 独立站能够帮助跨境…...
【Nas】X-DOC:在Mac OS X 中使用 WOL 命令唤醒局域网内 PVE 主机
【Nas】X-DOC:在Mac OS X 中使用 WOL 命令唤醒局域网内 PVE 主机 1、Mac OS X 端2、PVE 端(Debian Linux) 1、Mac OS X 端 (1)安装 wakeonlan 工具 brew install wakeonlan(2)唤醒 PVE 命令 …...
u盘装win10系统提示“windows无法安装到这个磁盘,选中的磁盘采用GPT分区形式”解决方法
我们在u盘安装原版win10 iso镜像时,发现在选择硬盘时提示了“windows无法安装到这个磁盘,选中的磁盘采用GPT分区形式”,直接导致了无法继续安装下去。出现这种情况要怎么解决呢?下面小编分享u盘安装win10系统提示“windows无法安装到这个磁盘…...
Linux系统之dc计算器工具的基本使用
Linux系统之dc计算器工具的基本使用 一、DC工具介绍二、dc命令的基本用法2.1 dc命令的help帮助信息2.2 dc命令基本用法2.3 dc命令常用操作符 三、dc命令的基本使用3.1dc命令的用法步骤3.2 简单数学计算3.3 通过文件来计算3.4 使用--expression计算3.5 使用dc命令进行高精度计算…...
使用Python计算相对强弱指数(RSI)进阶
使用Python计算相对强弱指数(RSI)进阶 废话不多说,直接上主题:> 代码实现 以下是实现RSI计算的完整代码: # 创建一个DataFramedata {DATE: date_list, # 日期CLOSE: close_px_list, # 收盘价格 }df pd.DataF…...
vue 解决:npm ERR! code ERESOLVE 及 npm ERR! ERESOLVE could not resolve 的方案
1、问题描述: 其一、需求为: 想要安装项目所需依赖,成功运行 vue 项目,想要在浏览器中能成功访问项目地址 其二、问题描述为: 在 package.json 文件打开终端平台,通过执行 npm install 命令,…...
Android 原生开发与Harmony原生开发浅析
Android系统 基于Linux ,架构如下 底层 (Linux )> Native ( C层) > FrameWork层 (SystemService) > 系统应用 (闹钟/日历等) 从Android发版1.0开始到现在15,经历了大大小小的变革 从Android6.0以下是个分水岭,6.0之前权限都是直接卸载Manifest中配置 6.0开始 则分普…...
VIVO售后真好:屏幕绿线,4年免费换屏
只要亮屏就有。这也太影响使用了。 本来想换趁机换手机,看了VIVO发布的X200,决定等明年的X200 ULTRA。手头这个就准备修。 查了一下价格,换屏1600,优惠1100。咸鱼上X70 PRO也就800。能不能简单维修就解决呢?于是联系…...
数据类型【MySQL】
文章目录 建立表查看表删除表数据类型floatcharvarcharchar&&varchar 时间日期类型enum和setenum和set查找 建立表 mysql> create table if not exists user1(-> id int ,-> name varchar (20) comment 用户名 ,-> password char (32) comment 用户名的…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
