阿里一面:说说看线程池的执行流程和原理?线程池的拒绝策略有哪些?如何确定线程池的核心线程数?如何优雅的关闭线程池?

基于CH32X035的USB双K型热电偶温度计:硬件设计、冷端补偿与信号放大详解 本文详细介绍了基于CH32X035单片机设计USB双K型热电偶温度计的完整方案。重点解析了硬件设计中的核心挑战:如何利用精密运放GS8552-SR进行信号放大,以及采用NTC热敏电阻和查表法实现精确的冷端补偿。项目通过USB供电通信,实现了双路高精度温度测量与显示,为电子爱好者和工程师提供了实用的参考设计。 阅读详情

面试概览:

  • 请说说看什么是线程池?以及为什么使用线程池开发而非单纯的多线程开发?

  • 请说说看线程池的实现原理和执行流程?

  • 如果让你设计一个线程池,那么这个线程池应该有哪些核心参数?

  • 你刚刚有提到线程池的拒绝策略,能说说看具体有哪几种拒绝策略以及它们的适用场景吗?

  • 在实际开发过程中你会如何确定线程池的核心线程数?

  • 如果关闭线程池的时候任务没执行完,如何优雅地关闭线程池?

  • 请简单的实现一个线程池?

面试官:请说说看什么是线程池?以及为什么使用线程池开发而非单纯的多线程开发?

线程池的定义

线程池是一种线程复用技术,它维护着多个线程等待监督管理者分配可并发执行的任务。处理过程中,将任务添加到队列,然后在线程创建后自动启动这些任务。

使用线程池而非单纯多线程开发的原因

  1. 降低资源消耗:

    • 线程池通过重复利用已创建的线程来执行任务,避免了线程的频繁创建和销毁所带来的开销。相比之下,单纯的多线程开发在每次需要执行任务时都会创建新的线程,这会导致资源的浪费和性能的下降。

  2. 提高响应速度:

    • 当任务到达时,线程池可以立即分配一个空闲线程来执行任务,而无需等待线程的创建。这提高了系统的响应速度,尤其是在处理大量并发请求时。

  3. 提高线程的可管理性:

    • 线程是稀缺资源,如果无限制地创建线程,不仅会消耗系统资源,还会降低系统的稳定性。线程池提供了一种统一分配、调优和监控线程的方式,使得线程的管理更加简单和高效。

  4. 避免大量线程的创建导致的内存问题:

    • 在多线程开发中,如果短时间内创建大量线程,可能会使内存到达极限,并出现“OutOfMemory”错误。而线程池通过限制最大线程数来避免这种情况的发生,当线程数达到最大值时,新的任务会被放入队列中等待执行。

面试官:请说说看线程池的实现原理和执行流程?

一、线程池的主要组件

  1. 工作线程:在线程池中创建的线程,等待并处理任务。

  2. 任务队列:待处理的任务队列,当有新任务时,任务会被放入队列中等待执行。

  3. 线程池管理器:管理线程池中线程的生命周期,处理任务调度、线程创建和销毁等。

二、线程池的实现原理

图片

  1. 线程复用:线程池通过复用线程来避免频繁创建和销毁线程的开销。当有新的任务到来时,线程池会判断当前是否有空闲线程,如果有,则直接将任务分配给空闲线程执行;如果没有,则根据线程池的配置策略(如核心线程数、最大线程数等)来决定是否创建新的线程。

  2. 任务调度:线程池中的任务调度器负责将任务从任务队列中取出,并分配给空闲的工作线程执行。任务调度器通常会采用先进先出(FIFO)的策略来确保任务的顺序执行。

  3. 线程管理:线程池管理器负责线程的创建、销毁、状态监控以及任务调度等工作。它会根据线程池的配置参数(如核心线程数、最大线程数、空闲线程存活时间等)来动态调整线程池的规模,以确保系统的稳定性和性能。

  4. 任务执行:工作线程从任务队列中取出任务后,会执行相应的任务逻辑。任务执行完毕后,工作线程会回到线程池中等待下一个任务的到来。

  5. 线程回收:当线程池中的工作线程空闲时间超过设定的阈值时,线程池管理器会将其回收,以减少系统资源的占用。同时,当系统不再需要线程池时,可以调用线程池的关闭方法来释放所有资源。

三、线程池的状态转换

线程池的状态转换是其实现原理中的重要部分。线程池通常有以下五种状态:

图片

  1. RUNNING:能接收新提交的任务,也能处理阻塞队列中的任务。

  2. SHUTDOWN:关闭状态,不再接收新提交的任务,但可以继续处理阻塞队列中已保存的任务。

  3. STOP:不接受任务,也不处理阻塞队列中的任务,会中断正在执行的任务。

  4. TIDYING:所有的任务已终止,工作线程数量为0,线程池将转化到TIDYING状态,即将要执行terminated()钩子方法。

  5. TERMINATED:terminated()方法已经执行结束,线程池已完全终止。

四、线程池的执行流程

线程池的执行流程主要涉及核心线程、工作队列、非核心线程以及拒绝策略等关键要素。以下是线程池执行流程的详细解释:

图片

  1. 任务提交:

    • 当出现一个新的线程任务时,线程池会首先尝试在线程池中分配一个空闲线程来执行这个任务。

  2. 核心线程判断:

    • 如果线程池中没有空闲线程,线程池会判断当前“存活线程数”是否小于核心线程数(corePoolSize)。

    • 如果“存活线程数”小于核心线程数,线程池会创建一个新的线程来处理新任务。

  3. 工作队列判断:

    • 如果“存活线程数”等于核心线程数,线程池会判断工作队列是否已满。

    • 如果工作队列未满(即还有位置可以存放任务),线程池会将新任务放入工作队列中等待,等线程池中出现空闲线程时,再按照“先进先出”的规则分配执行。

  4. 非核心线程判断:

    • 如果工作队列已满,线程池会判断当前存活线程数是否已经达到最大线程数(maximumPoolSize)。

    • 如果“存活线程数”小于“最大线程数”,线程池会创建一个新线程来执行新任务。

  5. 拒绝策略:

    • AbortPolicy:直接抛出RejectedExecutionException异常,阻止系统正常运行(这是默认策略)。

    • CallerRunsPolicy:用调用者所在线程来执行任务,不会抛出异常。

    • DiscardPolicy:不处理该任务,直接丢弃掉。

    • DiscardOldestPolicy:丢弃最老的未处理的任务请求。

    • RejectExecutionHandler:自定义拒绝策略,通过实现RejectedExecutionHandler接口来定义。

    • 如果“存活线程数”已经达到或超过最大线程数,且工作队列也已满,线程池会采用拒绝策略来处理新任务。常见的拒绝策略包括:

  6. 任务执行:

    • 一旦线程池中有空闲线程或新线程被创建,线程池就会从工作队列中取出任务,并调度给空闲线程执行。

  7. 线程回收:

    • 对于非核心线程,如果它们在指定的存活时间(keepAliveTime)内没有执行任务,那么这些线程将会被回收。

    • 当线程池处于SHUTDOWN状态时,它会停止接收新任务,但会继续处理已添加的任务。此时,空闲线程会被中断,线程池会逐步回收这些线程。

    • 当所有任务都已终止,且线程池中的线程数量已经减少到0时,线程池会进入TIDYING状态,并执行钩子函数terminated()。之后,线程池会进入TERMINATED状态,表示线程池已经彻底关闭。

面试官:如果让你设计一个线程池,那么这个线程池应该有哪些核心参数?

以下是一些线程池设计中通常需要考虑的核心参数:

  1. 核心线程数(Core Pool Size):

    • 这是线程池中始终保持的线程数量,即使某些线程处于空闲状态。核心线程数通常根据系统的需求和可用资源来确定。

  2. 最大线程数(Maximum Pool Size):

    • 这是线程池中允许的最大线程数量。当任务队列满时,线程池会尝试创建新的线程,直到达到最大线程数。

  3. 任务队列容量(Work Queue Capacity):

    • 任务队列用于存储等待执行的任务。队列的容量决定了在达到最大线程数之前,线程池可以容纳多少待处理的任务。

  4. 线程存活时间(Keep-Alive Time):

    • 当线程数量超过核心线程数时,多余的空闲线程在终止前等待新任务的最长时间。这个参数有助于在负载降低时释放资源。

  5. 时间单位(Time Unit):

    • 线程存活时间的时间单位,如毫秒、秒等。

  6. 线程工厂(Thread Factory):

    • 用于创建新线程的工厂类。通过自定义线程工厂,可以设置线程的优先级、是否为守护线程、线程名称等属性。

  7. 拒绝策略(Rejected Execution Handler):

    • 当线程池无法处理新任务时(因为线程数已达到最大且任务队列已满),将执行拒绝策略。常见的拒绝策略包括抛出异常、运行拒绝任务的回调、丢弃最旧的任务或丢弃最新的任务等。

  8. 是否允许核心线程超时(Allow Core Threads Time-Out):

    • 一个布尔值,指定核心线程是否也受线程存活时间的影响。如果设置为true,则核心线程在空闲时间超过线程存活时间后也会被终止。

  9. 任务优先级队列(Optional: Priority Work Queue):

    • 如果任务有不同的优先级,可以使用优先级队列来存储任务。这样,线程池会按照任务的优先级顺序来执行任务。

面试官:你刚刚有提到线程池的拒绝策略,能说说看具体有哪几种拒绝策略以及它们的适用场景吗?

首先,线程池的拒绝策略用于在任务队列已满且线程池无法处理新任务时,决定如何拒绝新的任务请求。

以下是几种Java线程池中常见的拒绝策略及其适用场景:

一、AbortPolicy(默认策略)

  • 作用:当任务无法被线程池执行时,会抛出一个RejectedExecutionException异常。

  • 适用场景:适用于对任务丢失敏感的场景,当线程池无法接受新任务时,希望立即知道并处理该异常。这种策略适合于那些不能容忍任务被丢弃或延迟执行的业务场景,因为它会立即通知调用者任务被拒绝,从而可以采取相应的措施,比如增加线程池大小、优化任务执行效率或者通知用户等待。

二、CallerRunsPolicy

  • 作用:当任务无法被线程池执行时,会直接在调用者线程中运行这个任务。如果调用者线程正在执行一个任务,则会创建一个新线程来执行被拒绝的任务。

  • 适用场景:适用于希望调用者自己处理被拒绝的任务的场景,通常是由调用者自身的线程来执行被拒绝的任务。

三、DiscardPolicy

  • 作用:当任务无法被线程池执行时,任务将被丢弃,不抛出异常,也不执行任务。

  • 适用场景:适用于对任务丢失不敏感的场景。例如,如果任务是一些可以重复执行或不太重要的操作,那么可以使用这种策略。但是需要注意的是,使用这种策略可能会导致无法执行的任务被丢弃而不会得到通知,因此需要谨慎选择。

四、DiscardOldestPolicy

  • 作用:当任务无法被线程池执行时,线程池会丢弃队列中最旧的任务(即等待时间最长的任务),然后尝试再次提交当前任务。

  • 适用场景:适用于对新任务优先级较高的场景。例如,如果新任务比旧任务更重要或更紧急,那么可以使用这种策略来确保新任务能够被执行。但是需要注意的是,这种策略也可能导致一些旧任务被丢弃而不会得到执行。

除了以上四种常见的拒绝策略外,还可以根据实际需求自定义拒绝策略。自定义拒绝策略可以通过实现RejectedExecutionHandler接口并覆盖其rejectedExecution方法来实现。在自定义拒绝策略中,可以根据具体的业务逻辑来处理被拒绝的任务,比如记录日志、抛出自定义异常、执行备选方案等。

面试官:在实际开发过程中你会如何确定线程池的核心线程数?

以下是一些常见的线程池核心线程数的考虑因素和确定方法:

考虑因素

  1. 任务特性:

    • CPU密集型任务:这类任务主要耗费CPU资源,因此核心线程数通常设置为CPU可用核心的数量,以使CPU的利用率最大化。

    • IO密集型任务:这类任务大部分时间都在等待IO操作完成,因此核心线程数可以设置得更高,以充分利用CPU在等待IO操作时的空闲时间。通常,线程数会多于CPU核心数。

    • 混合型任务:这类任务既有计算又有IO操作,需要综合考虑两种任务的比例来决定核心线程数。

  2. 系统资源:

    • CPU核心数:系统的CPU核心数是限制线程数的重要因素。过多的线程可能导致CPU资源过度竞争,降低系统性能。

    • 内存容量:内存资源也是需要考虑的因素。过多的线程会占用更多的内存,可能导致内存不足的问题。

  3. 应用性能需求:

    • 吞吐量:如果应用需要处理大量的并发任务,那么可能需要更多的线程来提高吞吐量。

    • 响应速度:对于需要快速响应的应用,合理的线程数可以确保任务被及时处理。

  4. 任务执行时间和到达频率:

    • 如果任务执行时间较长,那么可能需要较少的线程数,因为每个线程会占用较长时间。

    • 如果任务到达频率较高,那么可能需要更多的线程来确保任务能够及时被处理。

确定方法

  1. 理论预估:

    • 对于CPU密集型任务,可以使用公式“核心线程数 = CPU核心数”或“核心线程数 = CPU核心数 + 1”进行预估。

    • 对于IO密集型任务,可以使用公式“核心线程数 = CPU核心数 / (1 - 阻塞系数)”或简单地设置为CPU核心数的两倍或多一点进行预估。

    • 对于混合型任务,需要根据具体情况综合考虑两种任务的比例,并使用相应的公式进行预估。

  2. 压测验证:

    • 通过负载测试和压力测试来观察系统的性能表现,如吞吐量、响应时间等。

    • 根据测试结果调整核心线程数,直到找到最佳的性能平衡点。

  3. 监控动态调整:

    • 在实际应用中,可以使用性能监控工具来监控系统的CPU使用率、内存使用情况和响应时间等指标。

    • 根据监控结果动态调整核心线程数,以适应负载的变化。

面试官:如果关闭线程池的时候任务没执行完,如何优雅地关闭线程池?

一、使用shutdown()方法

shutdown()方法是ExecutorService接口提供的一个用于关闭线程池的方法。它会启动线程池的关闭序列,执行以下操作:

  • 设置线程池的状态为SHUTDOWN,此时线程池不再接受新任务。

  • 中断空闲的线程,但不会中断正在执行的任务。

  • 等待已提交的任务执行完成。

调用shutdown()方法后,线程池会等待所有已提交的任务执行完毕,然后再关闭。如果需要等待线程池关闭完成,可以调用awaitTermination()方法。

二、使用shutdownNow()方法

shutdownNow()方法也是ExecutorService接口提供的一个用于关闭线程池的方法。与shutdown()方法不同,它会尝试立即关闭线程池,执行以下操作:

  • 设置线程池的状态为STOP。

  • 尝试停止所有正在执行的任务,通过中断线程的方式实现。

  • 返回等待执行的任务列表,这些任务在关闭时还未来得及执行。

  • 清空任务队列。

需要注意的是,shutdownNow()方法并不保证能停止所有正在执行的任务,因为中断线程只是设置了一个中断状态,具体能否立即生效还取决于线程内部的实现。因此,在调用shutdownNow()方法后,可能需要结合awaitTermination()方法等待一段时间,以确保尽可能多的任务能够停止。

三、优雅关闭线程池的步骤

  1. 调用shutdown()方法:首先调用shutdown()方法,拒绝新提交的任务,并等待已提交的任务执行完成。

  2. 调用awaitTermination()方法:使用awaitTermination()方法等待线程池中的所有任务都完成执行。该方法会阻塞当前线程,直到所有任务都完成执行、超时发生或当前线程被中断。

  3. 处理未完成的任务:如果在超时时间内所有任务没有完成,可以调用shutdownNow()方法强制停止未执行完的任务。但需要注意,这可能会导致任务数据丢失或其他问题。

  4. 捕获和处理异常:在关闭线程池的过程中,需要注意捕获和处理可能出现的异常,以确保程序的健壮性。

以下是一个优雅关闭线程池的示例代码:

ExecutorService executorService = Executors.newFixedThreadPool(10);  
// 提交任务给线程池  for (int i = 0; i < 100; i++) {      executorService.submit(() -> {          // 模拟任务执行          try {              TimeUnit.SECONDS.sleep(1);          } catch (InterruptedException e) {              Thread.currentThread().interrupt();          }          System.out.println("任务执行完成");      });  }  
// 关闭线程池  try {      // 拒绝新任务,等待已提交任务执行完成      executorService.shutdown();      // 等待一段时间,确保所有任务都执行完成      if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {          // 如果超时仍未完成,则强制关闭线程池          List<Runnable> notExecutedTasks = executorService.shutdownNow();          System.out.println("有 " + notExecutedTasks.size() + " 个任务未执行完成");      }  } catch (InterruptedException e) {      // 当前线程被中断,需要重新关闭线程池      executorService.shutdownNow();      Thread.currentThread().interrupt();  }

在这个示例中,我们首先使用shutdown()方法拒绝新任务,并等待已提交的任务执行完成。然后,使用awaitTermination()方法等待一段时间,以确保所有任务都执行完成。如果超时仍未完成,则使用shutdownNow()方法强制关闭线程池,并处理未执行的任务。在关闭线程池的过程中,我们还捕获了InterruptedException异常,以确保程序的健壮性。

面试官:请简单的实现一个线程池?

实现一个线程池需要处理线程管理、任务队列、任务调度、线程生命周期控制等多个方面。

以下是一个基本的Java线程池实现示例:

import java.util.concurrent.BlockingQueue;  import java.util.concurrent.LinkedBlockingQueue;  import java.util.List;  import java.util.ArrayList;  import java.util.concurrent.atomic.AtomicInteger;  
public class SimpleThreadPool {      private final BlockingQueue<Runnable> taskQueue;      private final List<Worker> workers;      private final AtomicInteger workerCount;      private final int corePoolSize;      private final int maximumPoolSize;      private volatile boolean isShutdown;  
    // Worker class that extends Thread      private class Worker extends Thread {          private Runnable currentTask;  
        public Worker() {              workerCount.incrementAndGet();          }  
        public void runTask(Runnable task) {              currentTask = task;              currentTask.run();              currentTask = null;          }  
        @Override          public void run() {              while (!isShutdown || !taskQueue.isEmpty()) {                  try {                      Runnable task = taskQueue.take();                      runTask(task);                  } catch (InterruptedException e) {                      Thread.currentThread().interrupt(); // Restore interrupt status                  }              }              workerCount.decrementAndGet();          }      }  
    public SimpleThreadPool(int corePoolSize, int maximumPoolSize) {          this.corePoolSize = corePoolSize;          this.maximumPoolSize = maximumPoolSize;          this.taskQueue = new LinkedBlockingQueue<>();          this.workers = new ArrayList<>();          this.workerCount = new AtomicInteger(0);          this.isShutdown = false;  
        // Pre-start core number of workers          for (int i = 0; i < corePoolSize; i++) {              Worker worker = new Worker();              workers.add(worker);              worker.start();          }      }  
    public void execute(Runnable task) {          if (isShutdown) {              throw new IllegalStateException("ThreadPool is shut down");          }  
        if (workerCount.get() < maximumPoolSize) {              // If less than maximum pool size, start a new worker              Worker worker = new Worker();              workers.add(worker);              worker.start();              worker.runTask(task); // Run the task immediately if the worker is just started          } else {              // Otherwise, put the task in the queue              try {                  taskQueue.put(task);              } catch (InterruptedException e) {                  Thread.currentThread().interrupt(); // Restore interrupt status                  throw new RuntimeException(e);              }          }      }  
    public void shutdown() {          isShutdown = true;          // Optionally, interrupt all workers to terminate them immediately          // for (Worker worker : workers) {          //     worker.interrupt();          // }  
        // Alternatively, wait for all tasks to complete by not interrupting workers          // and letting them terminate naturally as the queue empties      }  
    // Additional methods like shutdownNow(), awaitTermination(), etc., can be added for a more complete implementation  
    public static void main(String[] args) throws InterruptedException {          SimpleThreadPool pool = new SimpleThreadPool(2, 4);  
        for (int i = 0; i < 10; i++) {              int taskId = i;              pool.execute(() -> {                  System.out.println("Executing task " + taskId + " by " + Thread.currentThread().getName());                  try {                      Thread.sleep(1000); // Simulate some work                  } catch (InterruptedException e) {                      Thread.currentThread().interrupt();                  }              });          }  
        // Shutdown the pool after some time to let tasks complete          Thread.sleep(5000);          pool.shutdown();  
        // Optionally, wait for all workers to terminate          // while (pool.workerCount.get() > 0) {          //     Thread.sleep(100);          // }      }  }

解释

  1. SimpleThreadPool 类:

    • taskQueue: 一个阻塞队列,用于存储待执行的任务。

    • workers: 一个列表,存储所有工作线程。

    • workerCount: 一个原子整数,用于跟踪当前活动的工作线程数。

    • corePoolSize 和 maximumPoolSize: 分别表示线程池的核心大小和最大大小。

    • isShutdown: 一个标志,表示线程池是否已关闭。

  2. Worker 内部类:

    • 继承自Thread,表示一个工作线程。

    • currentTask: 当前正在执行的任务。

    • runTask(Runnable task): 运行任务的方法。

    • run(): 工作线程的主循环,不断从任务队列中取任务并执行,直到线程池关闭或任务队列为空。

  3. 构造方法:

    • 初始化线程池的参数,并预启动核心数量的工作线程。

  4. execute(Runnable task) 方法:

    • 如果线程池已关闭,则抛出异常。

    • 如果当前活动的工作线程数小于最大池大小,则启动一个新的工作线程并立即运行任务。

    • 否则,将任务放入任务队列中等待执行。

  5. shutdown() 方法:

    • 设置关闭标志,可以选择立即中断所有工作线程,或者等待任务队列中的任务完成。

  6. main 方法:

    • 创建一个线程池并提交一些任务。

    • 等待一段时间后关闭线程池。

注意

  • 这个实现没有处理线程池的一些高级特性,如拒绝策略、线程工厂、线程保持活动时间等。

  • 在实际应用中,应该使用Java标准库中的ThreadPoolExecutor类,它提供了更完整和健壮的线程池实现。

  • 这个实现中的shutdown()方法只是设置了关闭标志,并没有实际中断工作线程。在实际应用中,你可能需要更复杂的关闭逻辑,比如等待所有任务完成或者立即中断所有工作线程。

下面再给出 Python 实现的线程池。

import threading  import queue  import time  from typing import Callable, Any  
class ThreadPool:      def __init__(self, num_threads: int):          self.tasks = queue.Queue()          self.threads = []          self.shutdown_flag = threading.Event()          self.num_threads = num_threads  
        # Create and start worker threads          for _ in range(num_threads):              thread = threading.Thread(target=self.worker)              thread.start()              self.threads.append(thread)  
    def worker(self):          while not self.shutdown_flag.is_set():              try:                  # Get a task from the queue (blocks if empty)                  func, args, kwargs = self.tasks.get(timeout=1)  
                # Execute the task                  try:                      func(*args, **kwargs)                  except Exception as e:                      print(f"Error executing task: {e}")  
                # Task done, mark it as processed                  self.tasks.task_done()              except queue.Empty:                  # If the queue is empty and we're shutting down, exit the loop                  if self.shutdown_flag.is_set() and self.tasks.empty():                      break  
    def submit(self, func: Callable, *args: Any, **kwargs: Any):          # Add a task to the queue          self.tasks.put((func, args, kwargs))  
    def shutdown(self, wait: bool = True):          # Set the shutdown flag          self.shutdown_flag.set()  
        # Optionally wait for all tasks to be completed          if wait:              self.tasks.join()  
        # Join all threads          for thread in self.threads:              thread.join()  
# Example usage:  def example_task(n):      print(f"Task {n} is running")      time.sleep(2)      print(f"Task {n} is complete")  
if __name__ == "__main__":      # Create a thread pool with 3 threads      pool = ThreadPool(num_threads=3)  
    # Submit some tasks to the pool      for i in range(10):          pool.submit(example_task, i)  
    # Shutdown the pool after all tasks are submitted      time.sleep(5)  # Give some time for tasks to run      pool.shutdown(wait=True)
OpenClaw 从新手到中级完整教程【完整 持续更新版】 OpenClaw(曾用名 ClawdBot/Moltbot)是 2026 年最火的开源 AI Agent 项目,GitHub 已获得超过 68,000 星标。它不是普通的聊天机器人,而是一个真正能够执行任务的个人 AI 助理。 阅读详情

相关推荐

关于Oxford Radar RobotCar Dataset的学习笔记

https://oxford-robotics-institute.github.io/radar-robotcar-dataset/documentation 简介 雷达是 Navtech CTS350-X 调频连续波 (FMCW) 扫描雷达,在所使用的配置中提供 4.38 cm 的距离分辨率和 0.9 度的旋转分辨率,范围高达 163 m,同时提供对天气条件的稳健性这可能会给其他传感器模式带来麻烦。在其他配置中,Navtech CTS350-X 可以提供超过 650 m 的范围和更高的旋转速度。然而,对

禾烁的博客 5298

【阿里一面】你知道线程池的执行原理吗?如何优雅的关闭呢?

线程池的执行流程: 提交任务:客户端通过 execute 或 submit 方法将任务提交到线程池。 核心线程:如果当前运行的线程数小于核心线程数(corePoolSize),线程池会创建新的线程来执行任务,即使其他空闲的核心线程也可以执行新任务。 工作队列:如果当前运行的线程数已经达到核心线程数,任务会被放入工作队列(workQueue)中等待执行。 最大线程:如果工作队列已满且当前运行的线程数小于最大线程数(maximumPoolSize),线程池会创建新的线程来执行任务。 拒绝策略:如果当前运行的线

激流丶的博客 508

基于51单片机的多功能计算器全套设计

当今社会,随着人们物质生活的不断提高,电子产品已经走进了家家户户,无论是生活或学习,还是娱乐和消遣几乎样样都离不开电子产品,大型复杂的计算能力是人脑所不能胜任的,而且人脑比较容易出错。计算器作为一种快速通用的计算工具方便了用户的使用。计算器可谓是我们最亲密的电子伙伴之一。本设计着重在于分析计算器设计开发过程中的环节和步骤,并从实践经验出发对计算器设计做了详细的分析和研究。 本设计是以STC89C52单片机为核心的计算器模拟系统设计,输入采用5×8矩阵键盘,可以进行加、减、乘、除等十几种数字运算,同时支持括号

runweipa的博客 1744

Java并发编程--20-线程池拒绝策略与参数调优:CPU密集型与IO密集型的黄金公式

/ 生产级自定义线程池模板(核心参数全可控)// 1. 获取CPU核心数(基础依据)// 2. 核心参数配置// CPU密集型// IO密集型// 有界队列// 3. 自定义线程池new ArrayBlockingQueue<>(QUEUE_CAPACITY), // 有界队列new ThreadFactory() { // 自定义线程工厂(命名+优先级)@Override},

weisian的博客 5840

LLM - windows下的Dify离线部署:从镜像打包到无网环境部署(亲测,包含插件部署)

LLM - windows下的Dify离线部署:从镜像打包到无网环境部署(亲测,包含插件部署)

ocean00008899的博客 1290

STM32F405实战:手把手教你实现永磁同步电机无感FOC控制(附完整工程文件)

本文详细介绍了基于STM32F405微控制器实现永磁同步电机无感FOC控制的完整实战方案。文章从硬件搭建、CubeMX配置入手,逐步讲解了FOC核心算法、SVPWM调制,并重点阐述了如何结合HFI高频方波注入与滑模观测器(SMO)实现全速域无感控制。内容涵盖算法原理、代码实现、参数整定及调试技巧,并附有完整工程文件,为开发者提供从理论到实践的全面指导。

sun99的博客 267

Java并发编程--19-ThreadPoolExecutor七参数详解:拒绝Executors,手动掌控线程池

线程池通过ctl状态二进制值含义是否接收新任务是否处理队列任务RUNNING111…运行中✅ 是✅ 是SHUTDOWN000…关闭中❌ 否✅ 是STOP001…停止中❌ 否❌ 否TIDYING010…整理中❌ 否❌ 否TERMINATED011…已终止❌ 否❌ 否线程池七参数,核心要记牢,core是常驻,max是上限,keepAlive管临时,超时就销毁,队列是缓冲,有界才安全,线程工厂定名称,拒绝策略别乱选。任务提交三步走,核心→队列→最大,

weisian的博客 5898

可信启动方案设计

本博客简要解释了TF-A中的Measured-Boot可信启动设计实现。

AI-安全-功耗 1204

深度解析Java 线程池的实现原理

Java 系统的运行归根到底是程序的运行,程序的运行归根到底是代码的执行,代码的执行归根到底是虚拟机的执行,虚拟机的执行其实就是操作系统的线程在执行,并且会占用一定的系统资源,如CPU、内存、磁盘、网络等等。所以,如何高效的使用这些资源就是程序员在平时写代码时候的一个努力的方向。本文要说的线程池就是一种对 CPU 利用的优化手段。 线程池,百度百科是这么解释的: 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大

Janson_Lin 3954

基于大语言模型的学术论文阅读辅助分析系统的研究与应用

本文提出了一种基于大语言模型的学术论文阅读辅助分析系统PaperMind,旨在解决传统学术阅读方式面临的三大困境:信息定位困难、跨学科知识断层和手动整理耗时。系统采用检索增强生成(RAG)架构,通过PDF文档解析、语义分割、向量嵌入与FAISS向量检索相结合的技术路线,构建了完整的文档处理流水线。实验结果表明,系统在文档加载分割、向量检索与问答生成环节均达到预期性能指标,检索命中率最高达98%。该系统为学术文献智能化处理提供了可复用的技术方案,有效解决了通用大语言模型在学术场景中的幻觉引用、归因能力不足等问

huanghm88的专栏 95

sim800c插卡后指示灯还是一秒一闪无法接收发送短信,如何解决?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 1171

JAVA 线程池七大参数与四种拒绝策略

为什么要线程池对比每次 new Thread线程池创建/销毁开销每次都有复用,零额外开销线程数量无限制 → 资源耗尽有界,受控任务调度无队列缓冲、拒绝策略管理无监控、超时回收、优雅关闭记住一句话:不使用线程池直接 new Thread,在高并发下会产生「线程风暴」,几分钟打垮服务。坑说明1Executors 快捷方法无界队列/无限线程,OOM 元凶2队列和线程数都不限制双无界 = 挂3没给线程起名字故障时 jstack 无法定位是哪个池4忘了关线程池。

wangchunyu114的博客 154

DA14531之如何Debug(在线调试、Jlink仿真、串口打印)

在线调试和串口打印调试。在线调试是Keil软件配合Jlink编译、烧录、仿真为一体的,其操作包括:运行、停止、打断点,单步运行等。而串口打印调试,只需打开相关配置,让arch_printf()函数正常输出串口数据。若想在初始化完成后打印arch_printf(“goto Loop\r\n”);波特率为115200,接收到串口消息goto Loop。连好线后,点击仿真按钮,在线Jlink调试。

hejinwu1314的博客 1794

Java 线程池 ThreadPoolExecutor 深度剖析

Java 线程池 ThreadPoolExecutor 深度剖析 线程池是并发编程绕不开的核心。很多人会 newFixedThreadPool,但一旦线上出现队列积压、任务被丢弃,就不知所措。 这篇从原理、参数、执行流程、拒绝策略到如何正确配置,一次讲透。

爱上网的小徐的博客 541

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Java 线程池详解

fill:#333;important;important;fill:none;color:#333;color:#333;important;fill:none;fill:#333;height:1em;线程池核心参数配置队列选择拒绝策略4种策略监控与调优合理配置避免 OOM优雅关闭防止任务丢失要点说明参数配置根据任务类型选择 core/max/queue队列选择优先使用有界队列拒绝策略根据业务选择合适的策略监控定期监控队列大小、活跃线程数关闭。

2301_79404691的博客 1477

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

【Java零基础连载17】Java线程池精讲|核心参数、七大线程池、拒绝策略、线程池优化实战

企业开发严禁手动new Thread创建线程,必须使用线程池。很多新手疑惑:手动创建线程简单直观,为什么项目中坚决不用?核心痛点如下:线程频繁创建、销毁,产生巨大性能开销,浪费CPU和内存资源无并发限制,海量任务会无限创建线程,导致系统资源耗尽、服务宕机线程分散混乱,无法统一监控、统一管理、统一调度任务无队列缓冲,突发流量直接打垮服务线程池的诞生就是为了解决以上所有问题,它提前初始化线程、复用线程、管控并发数量、缓冲任务、优雅拒绝超额请求,是所有Java高并发项目的标准解决方案。

荏苒夕阳的博客 489

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Java线程池原理与高并发优化实战

线程池作为Java并发编程的核心组件,通过线程复用机制显著降低系统资源消耗。其工作原理基于生产者-消费者模型,通过核心线程数、任务队列等参数实现资源管控。在电商秒杀、即时通讯等高并发场景中,合理配置的线程池可使系统吞吐量提升40%以上,同时减少70%的GC开销。工程师需要重点掌握ThreadPoolExecutor的七大参数配置,特别是针对IO密集型与CPU密集型任务的差异化调优策略。阿里Java开发手册强调的线程池命名规范、有界队列使用等最佳实践,能有效预防OOM和线程泄漏问题。结合Spring Boot

WGH100817的博客 427

Java线程池核心原理与实战配置指南

线程池作为Java并发编程的核心技术,通过复用线程资源显著提升系统性能。其核心原理基于生产者-消费者模型,通过维护固定数量的工作线程和任务队列实现高效任务调度。在工程实践中,合理配置corePoolSize、maximumPoolSize、workQueue等参数对系统稳定性至关重要,特别是处理高并发请求或批量任务时。典型应用场景包括Web服务器请求处理、异步日志记录和大数据处理等。本文深入解析线程池的Worker复用机制和动态参数调整方案,并针对ArrayBlockingQueue和LinkedBlock

weixin_30681615的博客 300

Spring Boot线程池实战:核心参数、阻塞队列与优雅关闭

线程池是Java并发编程的核心工具,通过复用线程降低资源开销,提升系统吞吐能力。理解ThreadPoolExecutor的执行原理——先核心线程、再阻塞队列、后最大线程、最终拒绝策略——是合理配置参数的前提。在实际工程中,线程池的价值体现在应对突发流量、异步化处理任务以及保护系统稳定性上,但错误配置也会引发任务堆积、内存溢出或数据串号等风险。本文从核心参数取舍出发,梳理Spring Boot中创建线程池的正确方式,分析execute与submit的差异,对比LinkedBlockingQueue与Synch

weixin_33834075的博客 353

简历写“精通线程池”却被问倒?这篇文章让你彻底搞懂线程池的底层逻辑!

线程池远不止“创建几个线程执行任务”那么简单,它涉及7 大参数、执行流程、拒绝策略、线程数调优、异常处理、动态调整、优雅关闭等多个维度。只有把这些底层逻辑吃透,你在简历上写的“精通线程池”才名副其实,面试时也能从容应对面试官的各种追问。最后,建议你在实际项目中亲手配置一个线程池,结合压测工具(如 JMeter)验证参数的合理性,真正把知识转化为实战能力。如果你还有关于线程池的疑问,欢迎在评论区留言讨论!

varyall的专栏 48

线程池深度解析:从使用到原理的完整指南

javaint corePoolSize, // 核心线程数int maximumPoolSize, // 最大线程数long keepAliveTime, // 线程空闲时间TimeUnit unit, // 时间单位BlockingQueue<Runnable> workQueue, // 工作队列RejectedExecutionHandler handler // 拒绝策略java// 自定义线程池。

2501_93078354的博客 265

java核心技术-线程池基本原理以及常见面试题

文章目录线程池的实现原理线程池类继承关系ThreadPoolExecutorExecutor四种工具类ScheduledThreadPoolExecutorCompletableFuture用法 线程池的实现原理 线程池类继承关系 ThreadPoolExecutor Executor四种工具类 ScheduledThreadPoolExecutor CompletableFuture用法 ...

dreamzuora的博客 633

Java线程池原理、应用与调优实战指南

线程池是多线程编程中的核心组件,通过复用线程资源显著提升系统性能。其工作原理基于生产者-消费者模型,核心参数包括corePoolSize、maximumPoolSize和workQueue等配置项。在Java生态中,ThreadPoolExecutor提供了灵活的线程管理能力,能有效降低资源消耗、提高响应速度并防止系统过载。针对高并发场景,合理配置线程池参数和拒绝策略尤为关键,如CPU密集型任务建议线程数等于核心数+1,IO密集型则可适当扩大。实际应用中,线程池广泛服务于Web服务器、定时任务等场景,配合S

weixin_30723433的博客 361

Java 线程池深度解析:从使用到原理

线程池的核心价值在于通过资源复用降低系统开销,通过线程复用减少创建和销毁的成本,同时利用异步处理提升系统响应能力。在实际应用中,应避免盲目使用Executors快捷方法,而应根据具体业务场景精细配置各项参数。深入理解线程池的工作原理并掌握其最佳实践,是构建高并发、高可靠性系统的必备技能。合理运用这一利器,能够让你的应用在流量洪峰面前保持稳健运行。

2501_93078354的博客 306

Java线程池

摘要:本文深入探讨Java线程池在生产环境中的实践应用与风险防范。主要内容包括:1.适用场景分析:针对IO密集型、CPU密集型、异步解耦和定时任务提供配置策略;2.常见陷阱及解决方案:如无界队列OOM风险、父子任务死锁、线程泄漏、ThreadLocal污染等;3.高级技巧:动态线程池调整、线程隔离、全链路监控、优雅关闭等最佳实践;4.源码级原理剖析:ctl状态机、Worker类实现等底层机制。文章强调必须手动配置线程池参数,采用有界队列和合理拒绝策略,并提供完整的监控方案和异常处理机制,确保系统稳定性和性能

长河的博客 1222

Java线程池核心原理与生产环境实战指南

线程池是Java并发编程中的核心组件,通过线程复用和资源管控机制显著提升系统吞吐量。其工作原理基于任务队列与线程生命周期管理,支持配置核心线程数、最大线程数等关键参数。在IO密集型场景中,合理配置线程池可使QPS提升3倍以上,而动态调参技术能有效应对流量波动。典型应用包括Web服务处理、异步任务执行等场景,结合Micrometer监控可实时掌握线程活跃度、队列堆积等关键指标。需特别注意避免无界队列导致的OOM风险,推荐采用TransmittableThreadLocal解决跨线程上下文传递问题。

weixin_34293911的博客 372
上一篇: 八股文-基础知识-面试题汇总(一)
下一篇: MySQL线上执行语句,监控与日志不可少
Java_2017_csdn
博客等级 码龄10年 329粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值