java线程池

线程池核心参数

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

corePoolSzie

:线程池核心线程数。核心线程即使空闲也不会被销毁。(比如最大线程数为10,核心线程数为8,就算这8个线程空闲,也不会被销毁,但是如果第9个线程空闲,那么第9个线程会被销毁。)

maximumPoolSize

:线程池最大线程数。

keepAliveTime

:非核心线程空闲的最大存活时间(同上,第9个线程是非核心线程,空闲时间超过了keepAliveTime就会被销毁)

unit

:时间单位

workQueue

:阻塞队列,存在多种实现,按需选择

handler

:拒绝策略处理器,maximumPoolSize和workQueue被填满时,放不下新线程就会使用拒绝策略。

拒绝策略

AbortPolicy

:直接抛出一个任务被线程池拒绝的异常。

public class newThreadPoolExecutor {
    public static void main(String[] args) {
        // 创建线程池,最大线程数为10,核心线程数为8,线程空闲存活时间为100ms
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                8,                // 核心线程数
                10,               // 最大线程数
                100,              // 非核心线程存活时间
                TimeUnit.MILLISECONDS,   // 时间单位为毫秒
                new LinkedBlockingQueue<>(10),  // 阻塞队列,最大容量为10
                new ThreadPoolExecutor.AbortPolicy()  // 拒绝策略:直接抛出异常
        );
        // 提交20个任务,超过最大线程数和队列容量将触发拒绝策略
        int count = 0;
        for (int i = 0; i < 30; i++) {
            count++;
            final int finalCount = count;
            try {
                // 提交任务
                threadPoolExecutor.submit(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("这是线程 " + finalCount);
                        try {
                            Thread.sleep(1000);  // 模拟任务执行1秒钟
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                });
            } catch (RejectedExecutionException e) {
                e.printStackTrace();
                System.out.println("任务 " + finalCount + " 被拒绝执行!");
            }
        }
​
        // 关闭线程池
        threadPoolExecutor.shutdown();
    }
}
​
这是线程 1
这是线程 7
这是线程 5
这是线程 4
这是线程 3
这是线程 2
这是线程 6
这是线程 8
这是线程 19
这是线程 20
任务 21 被拒绝执行!
任务 22 被拒绝执行!
任务 23 被拒绝执行!
任务 24 被拒绝执行!
任务 25 被拒绝执行!
任务 26 被拒绝执行!
任务 27 被拒绝执行!
任务 28 被拒绝执行!
任务 29 被拒绝执行!
任务 30 被拒绝执行!
java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@6e0be858 rejected from java.util.concurrent.ThreadPoolExecutor@61bbe9ba[Running, pool size = 10, active threads = 10, queued tasks = 10, completed tasks = 0]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
    at ThreadPool.newThreadPoolExecutor.main(newThreadPoolExecutor.java:27)

DiscardPolicy

:静默拒绝(冷暴力),什么也不返回

这是线程 3
这是线程 1
这是线程 5
这是线程 4
这是线程 2
这是线程 8
这是线程 7
这是线程 6
这是线程 20
这是线程 19
这是线程 9
这是线程 12
这是线程 10
这是线程 14
这是线程 13
这是线程 11
这是线程 15
这是线程 17
这是线程 18
这是线程 16

CallerRunsPolicy

:当一个任务被提交到线程池时,如果线程池的线程数已经达到最大线程数,且任务队列也已经满了,那么 CallerRunsPolicy 并不会直接拒绝任务(即不抛出异常),而是将该任务交由 提交任务的线程 执行,也就是说,任务会在提交它的线程中运行,而不是由线程池的线程来处理。

更换输出的语句

 System.out.println("这是线程 " +Thread.currentThread().getName() + ",正在执行任务" + finalCount);
这是线程 pool-1-thread-1,正在执行任务1
这是线程 pool-1-thread-5,正在执行任务5
这是线程 pool-1-thread-6,正在执行任务6
这是线程 pool-1-thread-3,正在执行任务3
这是线程 pool-1-thread-4,正在执行任务4
这是线程 pool-1-thread-8,正在执行任务8
这是线程 pool-1-thread-2,正在执行任务2
这是线程 pool-1-thread-9,正在执行任务19
这是线程 pool-1-thread-7,正在执行任务7
这是线程 main,正在执行任务21
这是线程 pool-1-thread-10,正在执行任务20
这是线程 pool-1-thread-6,正在执行任务9
这是线程 pool-1-thread-2,正在执行任务12
这是线程 pool-1-thread-1,正在执行任务10
这是线程 pool-1-thread-10,正在执行任务15
这是线程 pool-1-thread-8,正在执行任务11
这是线程 main,正在执行任务22
这是线程 pool-1-thread-3,正在执行任务16
这是线程 pool-1-thread-9,正在执行任务18
这是线程 pool-1-thread-4,正在执行任务14
这是线程 pool-1-thread-5,正在执行任务17
这是线程 pool-1-thread-7,正在执行任务13
这是线程 pool-1-thread-4,正在执行任务23
这是线程 pool-1-thread-1,正在执行任务25
这是线程 pool-1-thread-9,正在执行任务24
这是线程 pool-1-thread-5,正在执行任务26
这是线程 pool-1-thread-10,正在执行任务27
这是线程 pool-1-thread-2,正在执行任务29
这是线程 pool-1-thread-6,正在执行任务28
这是线程 pool-1-thread-8,正在执行任务30

有的被main线程执行。

DiscardOldestPolicy

当线程池队列满了并且不能再分配任务时,DiscardOldestPolicy 会丢弃队列中最旧的任务,尝试为新的任务腾出空间。这意味着,队列中最旧的任务(如果当前任务队列已满且线程池无法再处理新任务)会被丢弃,而新的任务会被加入到线程池中执行。

这是线程 pool-1-thread-2,正在执行任务 2
这是线程 pool-1-thread-5,正在执行任务 5
这是线程 pool-1-thread-4,正在执行任务 4
这是线程 pool-1-thread-3,正在执行任务 3
这是线程 pool-1-thread-8,正在执行任务 8
这是线程 pool-1-thread-1,正在执行任务 1
这是线程 pool-1-thread-7,正在执行任务 7
这是线程 pool-1-thread-6,正在执行任务 6
这是线程 pool-1-thread-9,正在执行任务 19
这是线程 pool-1-thread-10,正在执行任务 20
这是线程 pool-1-thread-5,正在执行任务 21
这是线程 pool-1-thread-3,正在执行任务 28
这是线程 pool-1-thread-6,正在执行任务 27
这是线程 pool-1-thread-7,正在执行任务 25
这是线程 pool-1-thread-10,正在执行任务 23
这是线程 pool-1-thread-8,正在执行任务 24
这是线程 pool-1-thread-9,正在执行任务 22
这是线程 pool-1-thread-4,正在执行任务 26
这是线程 pool-1-thread-1,正在执行任务 30
这是线程 pool-1-thread-2,正在执行任务 29

阻塞队列

ArrayBlockingQueue

:适用于固定大小、任务量已知的场景。

特点:基于数组的有界阻塞队列。

实现机制:固定大小,必须在创建时指定容量。

适用场景

  • 任务量是已知的且有界的场景。

  • 希望控制队列大小以限制内存占用。

注意

  • 若队列已满,put 操作会阻塞;若队列为空,take 操作会阻塞。

        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 0,
                TimeUnit.SECONDS, new ArrayBlockingQueue<>(5));

LinkedBlockingQueue

:适用于任务数量不固定、队列可能增长的场景。

特点:基于链表的阻塞队列,容量可指定(默认无界,实际为 Integer.MAX_VALUE)。

实现机制

  • 无界模式下,队列大小仅受内存限制。

  • 有界模式下,防止过多任务积压。

适用场景

  • 任务数量不确定,需动态调整队列大小的场景。

  • 默认的 Executors.newFixedThreadPool() 就使用了此队列。

注意

  • 无界队列可能导致内存耗尽。

        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 0,
                TimeUnit.SECONDS, new LinkedBlockingQueue<>());

PriorityBlockingQueue

:适用于优先级任务调度的场景。

特点:基于优先级排序的无界阻塞队列。

实现机制

  • 内部使用堆结构实现,元素按自然顺序或自定义比较器排序。

  • 队列无容量限制,但需要合理控制元素数量。

适用场景

  • 需要根据优先级处理任务的场景(如调度系统)。

注意

  • 无法保证元素的 FIFO 顺序,仅按照优先级出队。

元素需实现comparable接口。否则就报错。

public class test {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0,
                TimeUnit.SECONDS, new PriorityBlockingQueue<>());
        for (int i = 0; i < 8; i++) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                        System.out.println("hello");
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }
    }
}
​
Exception in thread "main" java.lang.ClassCastException: ThreadPool.test$1 cannot be cast to java.lang.Comparable
    at java.util.concurrent.PriorityBlockingQueue.siftUpComparable(PriorityBlockingQueue.java:357)
    at java.util.concurrent.PriorityBlockingQueue.offer(PriorityBlockingQueue.java:489)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1371)
    at ThreadPool.test.main(test.java:10)

实现接口

// 包装任务类
class PriorityRunnable implements Runnable,Comparable<PriorityTask>{
    final int priority;
    private final Runnable task;
​
    public PriorityRunnable(int priority, Runnable task) {
        this.priority = priority;
        this.task = task;
    }
​
     @Override
    public int compareTo(PriorityTask other) {
        return Integer.compare(other.priority, this.priority); // 优先级高的先执行
    }
}

DelayQueue

:适用于延时任务和定时任务的场景。

特点:支持延迟的无界阻塞队列。

实现机制

  • 元素需实现 Delayed 接口,规定延迟时间。

  • 只有延迟时间到期的元素才能被取出。

适用场景

  • 延迟任务或定时任务的调度(如定时消息推送)。

注意

  • 延迟到期的任务出队可能略有延迟(时间粒度)。

SynchronousQueue:适用于直接交换任务的场景。

LinkedTransferQueue:适用于需要高效任务传输的场景。

BlockingDeque:适用于需要双端队列操作的场景。

线程池种类

FixedThreadPool

线程池中线程的数量是固定的。

如果所有线程都在工作,新任务会进入阻塞队列等待。

使用无界的 LinkedBlockingQueue 存储任务,防止线程池因任务过多而耗尽资源。阻塞队列可存Integer.MAX_VALUE,所以任务不会被拒绝,所以不指定决绝策略。

核心线程数跟最大线程数一致。

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(nThreads);

SingleThreadExecutor

  • 线程池中只有一个线程,所有任务按照提交顺序串行执行。

  • 如果线程意外终止,会创建一个新的线程继续执行任务。

  • 使用无界的 LinkedBlockingQueue

核心线程和最大线程都是1,

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

适用场景

  • 适用于需要顺序执行任务的场景,如日志记录、任务调度。

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

实际实现: 内部是 ThreadPoolExecutor,核心线程数和最大线程数均为 1。

CachedThreadPool

特点

  • 没有核心线程数 (corePoolSize = 0),最大线程数为 Integer.MAX_VALUE

  • 空闲线程存活时间为 60 秒,超过存活时间未被使用的线程将被回收。

  • 使用 SynchronousQueue,每个任务直接交给空闲线程,如果没有空闲线程则创建新线程。

核心线程0,

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

适用场景

  • 适合大量短期异步任务的场景,能够快速提供线程资源。

  • 不适合长期占用线程的任务,可能导致线程数量过多。

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

ScheduledThreadPool

有参构造为这样,可以指定核心线程数量,最大线程数量默认Integer.MAX_VALUE,存活时间0,延时队列。

    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

特点

  • 专门用于执行定时任务或周期性任务。

  • 核心线程数固定,非核心线程数无限制,且非核心线程空闲后立即回收。

  • 使用 DelayedWorkQueue 存储任务。

适用场景

  • 适用于定时执行任务的场景,例如定时备份、轮询服务。

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(corePoolSize);

实际实现: 使用 ScheduledThreadPoolExecutor 类,扩展自 ThreadPoolExecutor

SingleThreadScheduledExecutor

特点

  • 类似于单线程线程池,但专门用于执行定时任务。

  • 保证任务按提交顺序串行执行,适用于需要顺序执行的定时任务。

内部只有一个线程。

    public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }

适用场景

  • 适用于需要单一线程按顺序执行定时任务的场景。

ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();

应该手动 new ThreadPoolExecutor 来创建线程池。

可能因为资源耗尽导致 OOM 问题。

线程池提交的任务可以被撤回吗?

可以调用生成的future对象的cancel方法撤回。

<think>我们正在讨论Java线程池的使用和原理。根据引用内容,线程池Java中主要通过ThreadPoolExecutor类实现,从JDK5开始内置支持。线程池的好处包括重用线程、控制并发数量、管理线程生命周期等。常见的线程池类型有:FixedThreadPool(固定容量)、CachedThreadPool(缓存)、SingleThreadExecutor(单线程)、ScheduledThreadPool(定时任务)以及通过ThreadPoolExecutor自定义创建。我们将分步骤讲解:1.线程池的核心原理2.创建线程池的五种方式(包括不推荐的原因)3.重点讲解ThreadPoolExecutor及其参数4.线程池的工作机制(任务提交、执行、拒绝策略等)5.使用示例注意:根据引用[3]和[4],ThreadPoolExecutor是构建线程池的核心类,因此我们将重点分析。步骤1:线程池的核心原理线程池通过预先创建一定数量的线程并维护它们,避免频繁创建和销毁线程的开销。当有任务提交时,线程池分配空闲线程执行任务;若没有空闲线程,任务将被放入队列等待;当队列满时,根据设定的拒绝策略处理。步骤2:创建线程池的五种方式(引用[3]和[5])1.newCachedThreadPool:创建一个可缓存的线程池,线程数可无限增加(最大为Integer.MAX_VALUE),空闲线程默认60秒回收。不推荐原因:可能创建过多线程导致OOM。2.newFixedThreadPool:固定大小的线程池,使用无界队列(LinkedBlockingQueue)。不推荐原因:无界队列可能堆积大量任务导致OOM。3.newSingleThreadExecutor:只有一个线程的线程池,同样使用无界队列。不推荐原因同上。4.newScheduledThreadPool:用于定时或周期性任务线程池。不推荐直接使用的原因是其最大线程数为Integer.MAX_VALUE,可能创建过多线程。5.推荐方式:直接使用ThreadPoolExecutor构造函数创建,可明确指定参数,避免资源耗尽。步骤3:ThreadPoolExecutor的七个参数(引用[3]和[4])构造方法如下:```javapublicThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime,TimeUnitunit,BlockingQueue<Runnable>workQueue,ThreadFactorythreadFactory,RejectedExecutionHandlerhandler)```1.corePoolSize:核心线程数,即使空闲也不会被回收(除非设置allowCoreThreadTimeOut)2.maximumPoolSize:最大线程数3.keepAliveTime:非核心线程的空闲存活时间4.unit:存活时间单位5.workQueue:任务队列(常用有ArrayBlockingQueue有界队列,LinkedBlockingQueue无界队列,SynchronousQueue同步移交队列)6.threadFactory:线程工厂,用于创建线程7.handler:拒绝策略(当线程池和队列都满时触发)步骤4:线程池的工作机制(任务提交执行流程)1.提交任务后,如果当前线程数小于corePoolSize,则创建新线程执行(即使有空闲线程)。2.如果当前线程数>=corePoolSize,则将任务放入workQueue。3.如果队列已满,且线程数小于maximumPoolSize,则创建新的非核心线程执行。4.如果队列已满且线程数达到maximumPoolSize,则触发拒绝策略。拒绝策略(handler)有四种:-AbortPolicy(默认):抛出RejectedExecutionException-CallerRunsPolicy:由调用线程执行该任务-DiscardPolicy:丢弃任务,不抛异常-DiscardOldestPolicy:丢弃队列最前面的任务,然后重试步骤5:使用示例(以ThreadPoolExecutor为例)下面是一个自定义线程池的示例:```javaimportjava.util.concurrent.*;publicclassThreadPoolExample{publicstaticvoidmain(String[]args){//创建线程池ThreadPoolExecutorexecutor=newThreadPoolExecutor(2,//核心线程数5,//最大线程数60,//空闲线程存活时间TimeUnit.SECONDS,newArrayBlockingQueue<>(10),//有界队列,容量10Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());//拒绝策略:直接抛出异常//提交任务for(inti=0;i<15;i++){finalinttaskId=i;executor.execute(()->{System.out.println("Task"+taskId+"isrunningonthread"+Thread.currentThread().getName());try{Thread.sleep(1000);//模拟任务执行}catch(InterruptedExceptione){e.printStackTrace();}});}//关闭线程池executor.shutdown();}}```注意:实际任务数15个,核心线程2个,最大线程5个,队列容量10个。因此前2个任务会创建核心线程执行,接下来的10个任务放入队列,然后第13、14、15个任务会创建非核心线程(共3个非核心线程,总线程数5个)。如果超过15个任务(比如16个),则会触发拒绝策略。最后,关于线程池的关闭,可以使用shutdown()(等待已提交任务完成)或shutdownNow()(尝试中断所有线程,停止任务)。总结:使用线程池时,推荐直接使用ThreadPoolExecutor构造函数,根据实际需求设置参数,避免使用Executors工厂方法可能导致的资源耗尽问题。相关问题:1.线程池任务队列有哪些类型?各自特点是什么?2.如何合理设置线程池的核心线程数和最大线程数?3.线程池的拒绝策略有哪些?如何自定义拒绝策略?4.如何监控线程池的运行状态?5.线程池中线程是如何创建的?如何自定义线程工厂?</think>### Java线程池使用指南与原理分析 Java线程池通过`java.util.concurrent`包实现,核心类是`ThreadPoolExecutor`。线程池的核心思想是**复用线程**,避免频繁创建销毁线程的开销。线程池中的线程执行完任务后不会销毁,而是回到池中等待新任务[^2]。 --- #### **一、线程池的创建方式** Java提供5种创建线程池的方法(实际都是`ThreadPoolExecutor`的包装): 1. **固定大小线程池**(推荐) ```java ExecutorService fixedPool = Executors.newFixedThreadPool(5); // 固定5个线程 ``` - 特点:核心线程数=最大线程数,使用无界队列`LinkedBlockingQueue` - 风险:任务过多时可能导致OOM(队列无限增长)[^5] 2. **缓存线程池**(不推荐) ```java ExecutorService cachedPool = Executors.newCachedThreadPool(); ``` - 特点:线程数无上限(`Integer.MAX_VALUE`),空闲线程60秒回收 - 风险:高并发时可能创建大量线程导致OOM[^3] 3. **单线程池** ```java ExecutorService singlePool = Executors.newSingleThreadExecutor(); ``` - 特点:仅1个线程,保证任务顺序执行 - 风险:同固定线程池(无界队列问题) 4. **定时任务线程池** ```java ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3); ``` 5. **推荐做法:手动创建`ThreadPoolExecutor`** ```java ThreadPoolExecutor customPool = new ThreadPoolExecutor( 4, // 核心线程数 10, // 最大线程数 60, // 空闲线程存活时间(秒) TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), // 有界队列(容量100) new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 ); ``` --- #### **二、核心参数详解(7个关键参数)** ```java public ThreadPoolExecutor( int corePoolSize, // 核心线程数(常驻线程) int maximumPoolSize, // 最大线程数 long keepAliveTime, // 非核心线程空闲存活时间 TimeUnit unit, // 时间单位 BlockingQueue<Runnable> workQueue, // 任务队列 ThreadFactory threadFactory, // 线程工厂 RejectedExecutionHandler handler // 拒绝策略 ) ``` 1. **任务队列类型** - `ArrayBlockingQueue`:**有界队列**(推荐),避免OOM - `LinkedBlockingQueue`:**无界队列**(默认) - `SynchronousQueue`:不存储任务,直接移交线程 2. **拒绝策略**(当队列和线程池全满时触发) - `AbortPolicy`(默认):抛出`RejectedExecutionException` - `CallerRunsPolicy`:由调用者线程直接执行任务 - `DiscardPolicy`:静默丢弃任务 - `DiscardOldestPolicy`:丢弃队列最旧的任务 --- #### **三、线程池工作原理** 1. **任务提交流程**: - 当线程数 < `corePoolSize`,**创建新线程**执行任务 - 当线程数 >= `corePoolSize`,任务进入**工作队列** - 当队列已满且线程数 < `maximumPoolSize`,**创建临时线程**执行 - 当队列满且线程数达到`maximumPoolSize`,触发**拒绝策略**[^4] 2. **线程回收机制**: - 核心线程默认不回收(除非设置`allowCoreThreadTimeOut(true)`) - 非核心线程空闲超过`keepAliveTime`后自动销毁 --- #### **四、最佳实践** 1. **参数设置建议**: - CPU密集型任务:核心线程数 = CPU核数 + 1 - IO密集型任务:核心线程数 = 2 * CPU核数 - 使用**有界队列**防止资源耗尽 - 拒绝策略选择`CallerRunsPolicy`保证任务不丢失 2. **代码示例**: ```java ThreadPoolExecutor executor = new ThreadPoolExecutor( Runtime.getRuntime().availableProcessors(), // 核心线程数=CPU核数 Runtime.getRuntime().availableProcessors() * 2, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(500), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy() ); // 提交任务 executor.execute(() -> System.out.println("Task running")); // 优雅关闭 executor.shutdown(); executor.awaitTermination(1, TimeUnit.MINUTES); ``` 3. **注意事项**: - 避免使用`Executors`快捷方法(有OOM风险) - 监控线程池状态(通过`getActiveCount()`等方法) - 务必调用`shutdown()`释放资源 --- #### **五、原理解析** - **线程复用**:通过`Worker`类封装线程,循环从队列获取任务执行[^3] - **任务调度**:核心逻辑在`ThreadPoolExecutor.execute()`方法中 - **资源控制**:通过`BlockingQueue`实现生产者-消费者模型 > 线程池的本质是**资源池化技术**(Pooling),通过复用线程降低系统开销,同时提供流量缓冲和容错能力[^4]。 --- ### 相关问题 1. **为什么`FixedThreadPool`使用无界队列会导致OOM?如何避免?** 2. **线程池中`corePoolSize`和`maximumPoolSize`设置不当会产生什么后果?** 3. **如何实现一个自定义拒绝策略(如记录日志或降级处理)?** 4. **线程池的`shutdown()`和`shutdownNow()`有什么区别?** 5. **如何监控线程池的运行状态(如队列积压、活跃线程数)?** [^1]: ThreadPoolExecutor是Java线程池的核心实现类。 [^2]: JDK5开始内置线程池,线程执行后返回池中复用。 [^3]: 手动创建ThreadPoolExecutor可避免资源耗尽风险。 [^4]: 线程池通过队列缓冲和动态扩缩容管理任务。 [^5]: FixedThreadPool的无界队列可能导致OOM。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值