Java线程池详解

1,649 阅读3分钟

这篇文章和大家讲讲Java中的线程池:

常见的4中线程池:

1.Executors.newCachedThreadPool(); 创建一个可缓存的线程池,如果线程长度超过处理需求,可灵活处理回收空闲线程,若无可回收线程,则新建线程; 在这里插入图片描述 2.Executors.newFixedThreadPool(5); 创建指定数量的线程池,可控制线程最大并发数,超出的线程会在队列中等待; 在这里插入图片描述 3.Executors.newScheduledThreadPool(10); 创建一个定长线程池,支持定时及周期性任务回收; 在这里插入图片描述 可知道多长时间后执行,专门做定时任务的线程池; 4.Executors.newSingleThreadExecutor(); 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务 在这里插入图片描述 5.**Executors.defaultThreadFactory();**默认线程池 在这里插入图片描述

创建线程池的2钟方法:

  1. 第一种:
public static ExecutorService service = Executors.newFixedThreadPool(10);
public static class Thread01 extends Thread{
    @Override
    public void run() {
        System.out.println("当前线程"+Thread.currentThread().getId());
        int i = 10/2;
        System.out.println("运行线程"+i);
    }
}
public static class Runnable01 implements Runnable{
    @Override
    public void run() {
        System.out.println("当前线程"+Thread.currentThread().getId());
        int i = 10/2;
        System.out.println("运行线程"+i);
    }
}

启动:

service.execute(new Thread01());
service.execute(new Runnable01());
  1. 第二种
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
        200,
        10,
        TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(10000),
        Executors.defaultThreadFactory(),
        new ThreadPoolExecutor.AbortPolicy());

此种方法创建的线程池有7大参数,我们知道了其意义,才可合理的运用他,我们进入其底层实现,如图 : 在这里插入图片描述

  • int corePoolSize:核心线程数,,其一直会在线程池保存(即时系统空闲,除非设置了allowCoreThreadTimeOut),即线程池创建以后就准备就绪的线程数量,就等待来接收异步任务.
  • int maximumPoolSize:最大线程数量,控制资源.
  • Long keepAliveTime:存活时间,如果当前的线程数量>核心数量,释放空闲线程(maximumPoolSize-corePoolSize)(只要线程空闲>存活时间).
  • TimeUnit unit:存活时间单位. BlockingQueue
  • workQueue:阻塞队列,如果任务有很多,多余的任务会先放在队列中,有线程空闲后,便会从队列中取新的线程继续执行.
  • ThreadFactory threadFactory:线程创建工厂. RejectedExecutionHandler
  • handler(拒绝策略):如果队列满了,存不了更多的任务,按照我们指定的拒绝策略拒绝执行我们的任务.

拒绝策略:

在这里插入图片描述 默认util包下有4种拒绝策略: 1.丢弃最老的任务 2.直接丢弃新来的任务,并且抛出异常 3.直接调用run方法的策略,相当于做了同步调用 4.直接丢弃新来的任务,但不 抛出异常

线程池工作顺序/流程:

1.线程池首先创建,准备好corePoolSize数量的核心线程,准备接收任务; 2.新来的任务,用corePoolSize准备好的空闲线程执行. 2.1 如果corePoolSize被任务占满,就将任务放在阻塞队列中,一旦有空闲的corePoolSize线程,便自己去任务对列中获取任务执行 2.2如果阻塞队列也满了,就直接开新线程执行,最大只能开到maximumPoolSize; 2.3如果maximumPoolSize也满了,maximumPoolSize-corePoolSize数量的空闲线程会在keepAliveTime指定的时间后自动销毁,最终保持到corePoolSize数量的线程. 2.4 如果线程开到了maximumPoolSize数量,还有新的任务进来,就会使用reject指定的拒绝策略来进行处理; 3所以线程的创建都是由threadFactory创建.

注意:new LinkedBlockingQueue<>();默认是Integer的最大值;(可能导致内存不够,故一定要存为定值数量)

使用线程池的好处:

  1. 降低资源消耗 通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗
  2. 提高响应速度 因为线程池中的线程没有没有超过线程池的最大上限时,有的线程处于等待分配任务状态,当任务来临时无需创建新的线程就能执行;
  3. 提高线程的可管理性 线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销;无限的创建和销毁线程不仅消耗系统资源,还降低系统的稳定性,