Java知识总结(十)

本文深入探讨了Java线程池的概念,包括ThreadPoolExecutor的构造参数、线程池的工作原理、线程复用、阻塞队列的种类,以及如何通过Executor和Executors创建线程池。线程池通过减少线程创建和销毁的开销,提高响应速度和可管理性,降低了资源消耗。文章还提到了四种常见的线程池类型以及如何关闭线程池,并讲解了阻塞队列在资源管理和线程调度中的重要作用。
摘要由CSDN通过智能技术生成

线程池

你要的线程池来了,还带有10道面试题和答案 (markdowner.net)

将一个或多个线程使用统一的方式进行调度和管理的技术,减少线程的创建和销毁所带来的开销。

线程池的作用(为什么要使用线程池)

  • 降低资源消耗:线程的创建和销毁都需要消耗资源,通过重复利用线程减少这方面消耗
  • 提高响应速度:当请求任务到达时,通常工作线程已经存在,不需要等待线程创建,直接执行
  • 提高线程的可管理:使用线程池统一对线程进行调度管理

线程池的创建

在JDK包下的JUC(java.util.concurrent)创建线程池的两种方法:ExecutorThreadPoolExecutor

image-20210731095047995

ThreadPoolExecutor

例子:

public class ThreadPoolDemo {
   

    private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 10,
            10L, TimeUnit.SECONDS, new LinkedBlockingQueue(100));

    public static void main(String[] args) {
   
        threadPoolExecutor.execute(new Runnable() {
   
            @Override
            public void run() {
   
                System.out.println("你好田中");
            }
        });
    }
}

ThreadPoolExecutor一共提供了四个构造函数,这里用参数最多构造函数说明。

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

当中三个最要的参数

  1. corePoolSize:线程池中核心线程数,所谓核心线程就是新创建的线程,若当前线程数量小于核心线程数,该线程是核心线程。

    作用定义最小可以同时运行线程的数目,核心线程默认情况下是一直存活在线程池中,可以通过allowCoreThreadTimeOut 设置核心线程的过期时间。

  2. **maximumPoolSize:**线程池中最大线程数量。线程总数=核心线程+非核心线程

  3. BlockingQueue workQueue:线程池中任务队列,当所有的核心线程都在工作时,新添加的任务会被放到任务队列中等待处理,若任务队列也满了那就创建非核心队列执行任务

其他参数

  1. keepAliveTime: 默认是非核心线程闲置超时时长,非核心线程若超过时间就会被销毁。若设置allowCoreThreadTimeOut = true,则会作用于核心线程

  2. TimeUnit unit:keepAliveTime的时间单位,TimeUnit是一个枚举类型

  3. **ThreadFactory threadFactory:**线程池提供创建新线程的线程工厂

  4. **RejectedExecutionHandler(饱和策略):**用来处理当前线程池中线程数量达到最大线程数目并且等待队列中也已经装满的情况。

    • ThreadPoolExecutor.AbortPolicy:直接抛出RejectedExecutionException异常拒绝新的任务
    • **ThreadPoolExecutor.DiscardPolicy:**不处理新任务,直接丢弃
    • **ThreadPoolExecutor.DiscardOldestPolicy:**丢弃最早未处理的任务请求
    • ThreadPoolExecutor.CallerRunsPolicy:不会抛出异常也不会丢弃任务,而是调用者运行自己的线程来完成新的任务请求,这种策略会降低新任务的提交速率。

    RejectedExecutionHandler 是一个接口,上面四种策略都是其实现类。

    若以上四种内置策略都无法满足,可以自定义策略。

execute()和submit()

两个方法都是将线程放入线程池中,区别在于execute方法没有返回值,submit方法有线程的返回值。

一般情况下是配合ExecutorService来使用的,在ExecutorService接口中声明了若干个submit方法的重载版本

<T> Future<T> submit(Callable<T> task)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值