Java中的线程池

为什么要有线程池?

如果并发线程数量很多,且每个线程执行任务时间很短,就会频繁创建和销毁线程,这种开销会大大降低系统的效率。为了线程的复用有了线程池这一概念。


1.线程池的创建

工具类Executors里提供了多种创建线程池的静态方法:

public class Executors {
    ...
    //创建一个固定大小的线程池。适用于可以预测线程数量的业务中,或者服务器负载较重,对当前线程数量进行限制。
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(...);
    }
    
    //可以扩大的线程池,最大值为Integer.MAX_VALUE。适用于服务器负载较轻,执行很多异步任务。
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(...);
    }   
    
    //单线程线程池。适用于需要保证顺序执行各个任务,并且在任意时间点,不会有多个线程活动的场景。
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(...));
    }

    //可以延时启动,定时启动的线程池。适用于需要多个后台线程执行周期任务的场景。
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

    //拥有多个任务队列的线程池。创建当前可用cpu数量的线程来并行执行,适用于大耗时操作并行执行
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool(...);
    }
    ...
}

2.线程池核心类ThreadPoolExecutor

源码中可以看出线程池有个核心类java.util.concurrent.ThreadPoolExecutor,谱系关系如下:

public class ThreadPoolExecutor extends AbstractExecutorService {}

public abstract class AbstractExecutorService implements ExecutorService {}

public interface ExecutorService extends Executor {}

public interface Executor {
    void execute(Runnable command);
}

Executor为最顶层的接口,只声明了一个用来执行任务的方法,ThreadPoolExecutor才是接口的实现类。下面来看ThreadPoolExecutor的部分源码:

public class ThreadPoolExecutor extends AbstractExecutorService {
    ...
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);
    }

    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,threadFactory, defaultHandler);
    }

    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), handler);
    }

    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {
        ...
    }
}

3.线程池参数

可以看出ThreadPoolExecutor有四个构造方法,前三个都是调用的最后一个。而最后一个构造方法有七个参数:

int corePoolSize; //核心线程数
int maximumPoolSize; //最大线程数
long keepAliveTime; //线程没有任务执行时保活时间。默认情况下,只有当池中的线程数 > corePoolSize时,此参数才会起作用,直到线程数 <= corePoolSize
TimeUnit unit; //keepAliveTime的时间单位
BlockingQueue<Runnable> workQueue; //任务队列。用来存储已被提交但尚未执行的任务,这里的任务是由ThreadPoolExecutor的execute方法提交的。
ThreadFactory threadFactory; //线程工厂。为线程池创建新线程
RejectedExecutionHandler handler; //任务拒绝策略。当前线程数已经达到maximumPoolSize而且任务队列已满,线程池会拒绝处理新任务。

4.线程池状态

private static final int RUNNING ;//创建线程池后,线程池处于running状态
private static final int SHUTDOWN ;//调用shutdown(),则RUNNING -> SHUTDOWN,此时线程池不能够接受新的任务,它会等待所有任务执行完毕;
private static final int STOP ;//调用shutdownNow(),则(RUNNING or SHUTDOWN ) -> STOP,此时线程池不接收新任务,不处理已添加的任务,并且会中断正在处理的任务;
private static final int TIDYING ;//当线程池在SHUTDOWN状态下,所有的任务已终止,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING;当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
private static final int TERMINATED ;//线程池处在TIDYING状态下,执行完terminated()之后,线程池彻底终止,就会由 TIDYING -> TERMINATED。

5.线程池几个重要方法

execute()
submit()
shutdown()
shutdownNow()
  • execute()方法实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,通过它可以向线程池提交一个任务,由线程池去执行。返回类型void。
  • submit()方法是在ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果。
  • shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务。
  • shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务。

6.任务缓存队列及排队策略

workQueue用来存放等待执行的任务,类型为BlockingQueue<Runnable>,通常可以取下面三种类型:

ArrayBlockingQueue //基于数组的先进先出队列,此队列创建时必须指定大小;
LinkedBlockingQueue //基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;
synchronousQueue //这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。

7.线程池拒绝策略

当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:

ThreadPoolExecutor.AbortPolicy;//丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy;//也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy;//丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy;//由调用线程处理该任务

 

内容概要:本文档详细介绍了一个基于MATLAB实现的跨尺度注意力机制(CSA)结合Transformer编码器的多变量时间序列预测项目。项目旨在精准捕捉多尺度时间序列特征,提升多变量时间序列的预测性能,降低模型计算复杂度与训练时间,增强模型的解释性和可视化能力。通过跨尺度注意力机制,模型可以同时捕获局部细节和全局趋势,显著提升预测精度和泛化能力。文档还探讨了项目面临的挑战,如多尺度特征融合、多变量复杂依赖关系、计算资源瓶颈等问题,并提出了相应的解决方案。此外,项目模型架构包括跨尺度注意力机制模块、Transformer编码器层和输出预测层,文档最后提供了部分MATLAB代码示例。 适合人群:具备一定编程基础,尤其是熟悉MATLAB和深度学习的科研人员、工程师和研究生。 使用场景及目标:①需要处理多变量、多尺度时间序列数据的研究和应用场景,如金融市场分析、气象预测、工业设备监控、交通流量预测等;②希望深入了解跨尺度注意力机制和Transformer编码器在时间序列预测中的应用;③希望通过MATLAB实现高效的多变量时间序列预测模型,提升预测精度和模型解释性。 其他说明:此项目不仅提供了一种新的技术路径来处理复杂的时间序列数据,还推动了多领域多变量时间序列应用的创新。文档中的代码示例和详细的模型描述有助于读者快速理解和复现该项目,促进学术和技术交流。建议读者在实践中结合自己的数据集进行调试和优化,以达到最佳的预测效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值