Java 线程池:深入理解与高效应用

在 Java 并发编程中,线程池是一种非常重要的技术。它可以有效地管理和复用线程,提高系统的性能和资源利用率。本文将深入探讨 Java 线程池的概念、原理、使用方法以及最佳实践,帮助读者更好地理解和应用线程池。

一、引言

在现代软件开发中,多线程编程是提高程序性能和响应性的重要手段。然而,直接创建和管理线程会带来一些问题,如线程创建和销毁的开销、资源浪费、线程过多导致的系统性能下降等。为了解决这些问题,Java 提供了线程池技术。线程池可以预先创建一定数量的线程,当有任务需要执行时,从线程池中获取一个空闲线程来执行任务,任务完成后,线程不会被立即销毁,而是返回线程池等待下一个任务。这样可以避免频繁地创建和销毁线程,提高系统的性能和资源利用率。

二、线程池的概念与原理

(一)线程池的基本概念

线程池是一种管理线程的工具,它包含了一组预先创建的线程和一个任务队列。当有任务需要执行时,将任务提交到任务队列中,线程池中的线程会从任务队列中获取任务并执行。如果任务队列中没有任务,线程会进入等待状态,直到有新的任务到来。当线程执行完一个任务后,它会继续从任务队列中获取下一个任务,或者进入等待状态,等待新的任务到来。

(二)线程池的工作原理

  1. 线程池的创建
    • 在创建线程池时,可以指定线程池的核心线程数量、最大线程数量、任务队列的类型和大小等参数。核心线程数量是指线程池中始终保持运行的线程数量,即使这些线程处于空闲状态。最大线程数量是指线程池中允许的最大线程数量,当任务队列已满且核心线程都在忙碌时,线程池会创建新的线程来执行任务,直到线程数量达到最大线程数量。
  2. 任务的提交
    • 当有任务需要执行时,可以通过线程池的execute方法或submit方法将任务提交到线程池中。execute方法用于提交一个Runnable任务,没有返回值;submit方法用于提交一个Callable任务,有返回值。提交任务后,线程池会根据当前的线程状态和任务队列的情况来决定如何执行任务。
  3. 线程的执行
    • 线程池中的线程会从任务队列中获取任务并执行。如果任务队列中没有任务,线程会进入等待状态,直到有新的任务到来。当线程执行完一个任务后,它会继续从任务队列中获取下一个任务,或者进入等待状态,等待新的任务到来。如果线程在执行任务过程中发生异常,线程池会创建一个新的线程来替代它,并继续执行任务。
  4. 线程池的关闭
    • 当不再需要线程池时,可以通过线程池的shutdown方法或shutdownNow方法来关闭线程池。shutdown方法会等待线程池中所有的任务执行完毕后再关闭线程池;shutdownNow方法会立即停止线程池的执行,并尝试中断正在执行任务的线程,返回尚未执行的任务列表。

三、Java 线程池的类型与创建

(一)Java 中的线程池类型

  1. FixedThreadPool(固定大小线程池)
    • FixedThreadPool是一种固定大小的线程池,它在创建时指定了线程池的核心线程数量和最大线程数量,并且这两个数量是相等的。当有任务提交到线程池中时,如果线程池中存在空闲线程,就会立即执行任务;如果线程池中没有空闲线程,就会将任务加入到任务队列中等待执行。
    • 特点:线程数量固定,不会因为任务的增加而创建新的线程,也不会因为任务的减少而销毁线程。适用于需要限制线程数量的场景,如服务器端的连接处理。
  2. CachedThreadPool(可缓存线程池)
    • CachedThreadPool是一种可缓存的线程池,它在创建时没有指定线程池的核心线程数量和最大线程数量。当有任务提交到线程池中时,如果线程池中存在空闲线程,就会立即执行任务;如果线程池中没有空闲线程,就会创建一个新的线程来执行任务。当线程在一段时间内没有执行任务时,就会被回收。
    • 特点:线程数量不固定,可以根据任务的数量自动调整线程数量。适用于执行大量短期任务的场景,如网页爬虫。
  3. ScheduledThreadPool(定时任务线程池)
    • ScheduledThreadPool是一种用于执行定时任务的线程池,它在创建时指定了线程池的核心线程数量。当有定时任务提交到线程池中时,线程池会创建一个新的线程来执行任务,并在任务执行完毕后将线程回收。如果在任务执行过程中发生异常,线程池会创建一个新的线程来替代它,并继续执行任务。
    • 特点:可以执行定时任务和周期性任务。适用于需要定期执行任务的场景,如定时备份数据。
  4. SingleThreadExecutor(单线程线程池)
    • SingleThreadExecutor是一种单线程的线程池,它在创建时只有一个核心线程。当有任务提交到线程池中时,这个核心线程会执行任务。如果任务在执行过程中发生异常,线程池会创建一个新的线程来替代它,并继续执行任务。
    • 特点:只有一个线程在执行任务,保证任务按照提交的顺序依次执行。适用于需要保证任务顺序执行的场景,如日志记录。

(二)创建线程池的方法

  1. 使用Executors工厂类创建线程池
    • Java 提供了Executors工厂类来方便地创建不同类型的线程池。可以使用Executors.newFixedThreadPoolExecutors.newCachedThreadPoolExecutors.newScheduledThreadPoolExecutors.newSingleThreadExecutor方法分别创建固定大小线程池、可缓存线程池、定时任务线程池和单线程线程池。
    • 示例代码:

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();}
}

  1. 使用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));}
}

四、线程池的任务提交与执行

(一)提交任务的方法

  1. 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();}
}

  1. 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();}
}

(二)任务的执行过程

  1. 线程从任务队列中获取任务
    • 线程池中的线程会不断地从任务队列中获取任务并执行。如果任务队列中没有任务,线程会进入等待状态,直到有新的任务到来。当有任务提交到线程池中时,线程池会根据当前的线程状态和任务队列的情况来决定如何执行任务。
  2. 任务的执行
    • 线程获取到任务后,会执行任务中的代码。如果任务在执行过程中发生异常,线程池会创建一个新的线程来替代它,并继续执行任务。如果任务执行成功,线程会继续从任务队列中获取下一个任务,或者进入等待状态,等待新的任务到来。
  3. 任务的返回结果
    • 如果提交的任务是一个Callable任务,并且使用了submit方法提交任务,那么可以通过Future对象来获取任务的返回结果。如果任务在执行过程中发生异常,Future对象的get方法会抛出相应的异常。

五、线程池的参数调整与性能优化

(一)线程池参数的含义与调整方法

  1. 核心线程数量(corePoolSize)
    • 核心线程数量是指线程池中始终保持运行的线程数量,即使这些线程处于空闲状态。当有任务提交到线程池中时,如果线程池中存在空闲线程,就会立即执行任务;如果线程池中没有空闲线程,就会将任务加入到任务队列中等待执行。如果任务队列已满且核心线程都在忙碌时,线程池会创建新的线程来执行任务,直到线程数量达到最大线程数量。
    • 调整方法:根据任务的类型和数量来调整核心线程数量。如果任务是 CPU 密集型的,即任务主要消耗 CPU 资源,可以将核心线程数量设置为与 CPU 核心数量相等或稍大一些,以充分利用 CPU 资源。如果任务是 I/O 密集型的,即任务主要消耗 I/O 资源,可以将核心线程数量设置得较大一些,以提高线程的并发度。
  2. 最大线程数量(maximumPoolSize)
    • 最大线程数量是指线程池中允许的最大线程数量。当任务队列已满且核心线程都在忙碌时,线程池会创建新的线程来执行任务,直到线程数量达到最大线程数量。如果任务队列已满且线程数量达到最大线程数量,那么新提交的任务将被拒绝执行。
    • 调整方法:根据系统的资源情况和任务的类型来调整最大线程数量。如果系统的资源比较充足,可以将最大线程数量设置得较大一些,以提高线程的并发度。如果系统的资源比较紧张,可以将最大线程数量设置得较小一些,以避免系统资源的过度消耗。
  3. 任务队列(workQueue)
    • 任务队列是用于存储等待执行的任务的队列。当有任务提交到线程池中时,如果线程池中存在空闲线程,就会立即执行任务;如果线程池中没有空闲线程,就会将任务加入到任务队列中等待执行。
    • 调整方法:根据任务的类型和数量来选择合适的任务队列类型和大小。如果任务是 CPU 密集型的,可以选择一个较小的任务队列,以避免任务在队列中等待时间过长。如果任务是 I/O 密集型的,可以选择一个较大的任务队列,以提高线程的并发度。常见的任务队列类型有ArrayBlockingQueueLinkedBlockingQueueSynchronousQueue等。
  4. 线程空闲时间(keepAliveTime)
    • 线程空闲时间是指线程在没有任务可执行时的最大等待时间。当线程在一段时间内没有执行任务时,就会被回收。如果线程空闲时间设置得过长,可能会导致线程资源的浪费;如果线程空闲时间设置得过短,可能会导致线程频繁地创建和销毁,增加系统的开销。
    • 调整方法:根据任务的类型和数量来调整线程空闲时间。如果任务是短期任务,可以将线程空闲时间设置得较短一些,以避免线程资源的浪费。如果任务是长期任务,可以将线程空闲时间设置得较长一些,以减少线程的创建和销毁次数。
  5. 拒绝策略(rejectedExecutionHandler)
    • 拒绝策略是指当任务队列已满且线程数量达到最大线程数量时,新提交的任务将被拒绝执行时采取的策略。Java 提供了四种拒绝策略,分别是AbortPolicyCallerRunsPolicyDiscardOldestPolicyDiscardPolicy
    • 调整方法:根据系统的需求和任务的重要性来选择合适的拒绝策略。如果任务比较重要,可以选择CallerRunsPolicy,让提交任务的线程自己执行任务;如果任务不太重要,可以选择DiscardPolicyDiscardOldestPolicy,直接丢弃新提交的任务。

(二)性能优化的技巧与注意事项

  1. 合理设置线程池参数
    • 根据任务的类型和数量来合理设置线程池的参数,如核心线程数量、最大线程数量、任务队列的类型和大小等。避免设置过大或过小的参数,以免影响系统的性能和资源利用率。
  2. 避免任务阻塞
    • 在任务执行过程中,尽量避免任务的阻塞,如 I/O 操作、数据库访问等。可以使用异步 I/O、连接池等技术来减少任务的阻塞时间,提高线程的并发度。
  3. 监控线程池状态
    • 可以使用 Java 的监控工具,如jconsoleVisualVM等,来监控线程池的状态,如线程数量、任务队列大小、任务执行时间等。根据监控结果来调整线程池的参数,以提高系统的性能和资源利用率。
  4. 避免线程泄漏
    • 在任务执行过程中,要注意避免线程泄漏。线程泄漏是指线程在执行任务过程中,由于某些原因没有正确地释放资源,导致线程一直处于运行状态,无法被回收。可以使用try-with-resources语句、finally块等方式来确保资源的正确释放。
  5. 考虑任务的优先级
    • 如果任务有不同的优先级,可以考虑使用优先级队列来存储任务,以便高优先级的任务能够优先执行。Java 提供了PriorityBlockingQueue类来实现优先级队列。

六、线程池的应用场景与实际案例

(一)应用场景

  1. 网络服务器
    • 在网络服务器中,需要同时处理多个客户端的连接请求。可以使用线程池来管理连接处理线程,提高服务器的并发处理能力。当有新的连接请求到来时,从线程池中获取一个空闲线程来处理连接,连接处理完毕后,线程返回线程池等待下一个连接请求。
  2. 数据库连接池
    • 在数据库访问中,频繁地创建和销毁数据库连接会带来很大的开销。可以使用线程池来管理数据库连接,提高数据库访问的效率。当有数据库访问请求到来时,从线程池中获取一个数据库连接来执行查询操作,查询完毕后,将数据库连接返回线程池等待下一个查询请求。
  3. 任务调度
    • 在任务调度中,需要定期执行一些任务。可以使用定时任务线程池来管理任务执行线程,提高任务调度的效率。当有定时任务需要执行时,从线程池中获取一个空闲线程来执行任务,任务执行完毕后,线程返回线程池等待下一个定时任务。
  4. 并行计算
    • 在并行计算中,需要同时执行多个计算任务。可以使用线程池来管理计算任务执行线程,提高并行计算的效率。将计算任务分解为多个子任务,提交到线程池中执行,最后将子任务的结果合并得到最终的计算结果。

(二)实际案例

  1. 网络服务器案例
    • 假设我们要开发一个简单的网络服务器,能够同时处理多个客户端的连接请求。可以使用线程池来管理连接处理线程,提高服务器的并发处理能力。
    • 示例代码:

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();}}
}

  1. 数据库连接池案例
    • 在数据库访问中,频繁地创建和销毁数据库连接会带来很大的开销。可以使用线程池来管理数据库连接,提高数据库访问的效率。
    • 示例代码:

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);}
}

  1. 任务调度案例
    • 在任务调度中,需要定期执行一些任务。可以使用定时任务线程池来管理任务执行线程,提高任务调度的效率。
    • 示例代码:

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);}
}

  1. 并行计算案例
    • 在并行计算中,需要同时执行多个计算任务。可以使用线程池来管理计算任务执行线程,提高并行计算的效率。
    • 示例代码:

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 应用程序。

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

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

相关文章

高级SQL技巧掌握

高级SQL技巧掌握 在数据驱动的时代,掌握SQL不仅仅是为了解决具体问题,它更像是一把钥匙,帮助你打开数据分析的大门。你准备好提升你的SQL技能了吗?在这篇文章中,我们将一起探索十个必备的高级SQL查询技巧,这些技巧将帮助你更有效率地进行数据处理与分析。 1. 常见表表达…

从0到1学习node.js(npm)

文章目录 一、NPM的生产环境与开发环境二、全局安装三、npm安装指定版本的包四、删除包 五、用npm发布一个包六、修改和删除npm包1、修改2、删除 一、NPM的生产环境与开发环境 类型命令补充生产依赖npm i -S uniq-S 等效于 --save -S是默认选项npm i -save uniq包的信息保存在…

webpack 老项目升级记录:从 node-sass 限制的的 node v8 提升至支持 ^node v22

老项目简介 技术框架 vue 2.5.17webpack 4.16.5"webpack-cli": "3.1.0""node-sass": "^4.7.2" 几个阶段 第一步&#xff1a;vue2 升级到最新 第一步&#xff1a;升级 vue2 至最新版本&#xff0c;截止到目前&#xff08;2024-10-…

解决RabbitMQ脑裂问题

文章目录 前言一、现象二、解决办法 前言 RabbitMQ脑裂 一、现象 RabbitMQ镜像群出现脑裂现象&#xff0c;各个节点的MQ实例都“各自为政”&#xff0c;数据并不同步。 二、解决办法 # 停止mq sh rabbitmq-server stop_app # 查看mq进程是否存在 ps -ef | grep rabbitmq # …

ATom:加州理工学院化学电离质谱仪(CIT-CIMS)的现场数据,V2版

目录 简介 摘要 代码 引用 网址推荐 知识星球 机器学习 ATom: In Situ Data from Caltech Chemical Ionization Mass Spectrometer (CIT-CIMS), V2 ATom&#xff1a;加州理工学院化学电离质谱仪&#xff08;CIT-CIMS&#xff09;的现场数据&#xff0c;V2版 简介 该数…

trueNas 24.10 docker配置文件daemon.json无法修改(重启被覆盖)解决方案

前言 最近听说truenas的24.10版本开放docker容器解决方案放弃了原来难用的k3s&#xff0c;感觉非常巴适&#xff0c;就研究了一下&#xff0c;首先遇到无法迁移老系统应用问题比较好解决&#xff0c;使用sudo登录ssh临时修改daemon.json重启docker后进行docker start 容器即可…

十一、数据库配置

一、Navicat配置 这个软件需要破解 密码是&#xff1a;123456&#xff1b; 新建连接》新建数据库 创建一个表 保存出现名字设置 双击打开 把id设置为自动递增 这里就相当于每一次向数据库添加一个语句&#xff0c;会自动增长id一次 二、数据库的增删改查 1、Vs 建一个控…

Java设计模式之代理模式(二)

一、CGLIB动态代理 JDK动态代理要求被代理的类必须实现接口&#xff0c;有很强的局限性&#xff0c;而CGLIB动态代理则不要求被代理类实现接口。简单的说&#xff0c;CGLIB会让生成的代理类继承被代理类&#xff0c;并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。…

二叉树详解:类型、特性与应用

二叉树详解&#xff1a;类型、特性与应用 二叉树&#xff08;Binary Tree&#xff09;是计算机科学和数据结构中的核心构造&#xff0c;广泛用于多种算法和系统的实现。其每个节点最多有两个子节点&#xff0c;即左子节点和右子节点。尽管其结构表面上相对简单&#xff0c;二叉…

在 Gitee 或 GitCode 上克隆 Dify 项目源码并启动 Docker 环境

在 Gitee 或 GitCode 上克隆 Dify 项目源码并启动 Docker 环境 第一步&#xff1a;克隆源码仓库 首先&#xff0c;使用以下命令将项目克隆到本地&#xff0c;确保您已经在 Gitee 或 GitCode 上配置了 SSH 密钥&#xff1a; git clone gitgitcode.com:Mingcai_Xiong/dify-cop…

git的学习之远程进行操作

1.代码托管GitHub&#xff1a;充当中央服务器仓库的角色 2.git远程进行操作 3.配置本地服务器的公钥 4.推送 5.git远程操作 pull .gitignore 6.给命令配置别名 git config --global alias.st status 7.标签管理 git tag -a [name] -m "XXX" [commit_id] 操作标签…

基于Python的自然语言处理系列(46):4-bit LLM 量化与 GPTQ

在本篇文章中&#xff0c;我们将深入探讨如何使用 GPTQ (Generative Pre-trained Quantization) 进行4-bit大语言模型(LLM)的量化。在大规模语言模型训练和推理的背景下&#xff0c;模型的量化不仅能够大大降低计算成本&#xff0c;还能够提高推理速度&#xff0c;因此对构建高…

正则表达式使用举例一(Python下)

目录 1 问题描述2 解决2.1 问题1的解决2.2 问题2的解决 摘要&#xff1a;本文给出了一个在Python语言中利用re包进行正则表达式匹配计算的例子。详细讲述了所写的正则表达式的含义&#xff0c;还对搜索结果对象的span()函数进行运用举例&#xff0c;从而成功提取出原字符串中的…

查找与排序-插入排序

1.直接插入排序的基本思想 假设n个数据元素关键字存储在静态数组a中&#xff0c;则直接插入排序的基本思想可做如下描述&#xff1a; &#xff08;1&#xff09;初始有序子序列由一个元素a[0] 组成&#xff1b; &#xff08;2&#xff09;从a[1]开始&#xff0c;对于序列中每…

安卓屏幕旋转(TODO)

要对整个安卓系统实现实时旋转&#xff0c;无论设备如何旋转&#xff0c;屏幕始终与设备的物理方向保持一致&#xff0c;涉及到修改 Android 系统级别的显示设置和传感器处理。这种需求不单单在应用层实现&#xff0c;而是需要对 Android 系统的 **frameworks** 和 **display s…

leetcode 75-13 k和数对的最大数目

我的思路 sort函数排序 然后双指针判断 这样时间复杂度nlgn 题解给出了一种空间换时间方法 用哈希表 注意一下写法 现在完全不会这样写 还有就是注意sort函数的代码 怎么写排序也给忘了 sort用的是什么排序方法

自由职业者的一天:作为小游戏开发者的真实工作日记

大家好&#xff0c;我是小蜗牛。 在这个快节奏的数字时代&#xff0c;自由职业者的生活往往充满了挑战与机遇。作为一名微信小游戏开发者&#xff0c;我的日常工作并不像人们想象中的那样充满光鲜亮丽的画面&#xff0c;而是由无数的编码、调试和创意碰撞组成的。今天&#xf…

MySQL 回收表碎片实践教程

前言&#xff1a; 在 MySQL 数据库中&#xff0c;随着数据的增删改操作&#xff0c;表空间可能会出现碎片化&#xff0c;这不仅会占用额外的存储空间&#xff0c;还可能降低表的扫描效率&#xff0c;特别是一些大表&#xff0c;在进行数据清理后会产生大量的碎片。本篇文章我们…

高并发-负载均衡

负载均衡在微服务架构中是一个重要的组成部分&#xff0c;旨在优化资源利用、提高服务可用性和确保系统的高可扩展性。以下是对微服务中的负载均衡的详细介绍&#xff0c;包括其原理、类型、实现方式以及相关的技术。 一、负载均衡的原理 负载均衡的基本原理是将进入系统的请…

Lesson11---stack

Lesson11—stack cstack的介绍使用以及模拟实现 文章目录 Lesson11---stack前言一、stack成员函数1.stack2.empty3.size4. top5.push6.pop 二、stack相关题目1. 最小栈2.栈的压入、弹出序列 三、模拟实现总结 前言 stack的介绍和使用stack是一种容器适配器&#xff0c;专门用…