Java线程池理解与学习

简介: 线程过多就容易引发内存溢出,因此我们有必要使用线程池的技术线程池的好处降低资源消耗: 通过重复利用已创建的线程降低线程创建和销毁造成的消耗提高响应速度: 当任务到达时,任务可以不需要等待线程创建就能立即执行提高线程管理性: 线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控

线程过多就容易引发内存溢出,因此我们有必要使用线程池的技术


线程池的好处


降低资源消耗: 通过重复利用已创建的线程降低线程创建和销毁造成的消耗

提高响应速度: 当任务到达时,任务可以不需要等待线程创建就能立即执行

提高线程管理性: 线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控


线程池的创建


线程池的真正实现类是ThreadPoolExecutor,其中具有七个重要参数

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

corePoolSize

核心线程数。默认情况下核心线程会一直存活,但是当将allowsCoreThreadTimeOut设置为true时,核心线程也会超时回收。核心线程最开始并不会立即创建而是等任务来了再创建,然后存活下去


maximumPoolSize

最大线程数 。线程池所能容纳的最大线程数。当活跃线程数达到该数值后,后续的新任务将会阻塞。最大线程数 = 核心线程数 + 非核心线程数


keepAliveTime

非核心线程闲置超时时间 。如果超过该时长,非核心线程将会回收


unit

超时单位 。指定KeepAliveTime超时时间的单位。


workQueue

任务队列 。当核心线程全被使用的时候,且任务队列未满时候就会先将任务放到任务队列中


threadFactory

线程工厂 。用于指定为线程创建新线程的方式


handler

拒绝策略 。当最大线程数达到饱和时候需要执行的饱和策略


任务队列

任务队列是基于阻塞队列实现的,即采用生产者消费者模式,在Java中需要实现BlockingQueue接口,但Java已经为我们提供了7种阻塞队列的实现


ArrayBlockingQueue


一个由数组结构构成的有界阻塞队列(数组结构可配合指针实现一个环形队列)


LinkedBlockingQueue


一个由链表结构构成的有界阻塞队列,在未指明容量时默认为Integer.MAX_VALUE


PriorityBlockingQueue


一个支持优先级排序的无界队列,对元素没有要求,可以实现Comparable接口来进行比较


DelayQueue


类似于PriorityBlockingQueue,是二叉堆形成的无界优先队列。要求元素都实现DelayQueue接口,通过执行时延从队列中提取任务,时间没到任务取不出来


SynchronousQueue


一个不存储元素的阻塞队列,消费者线程调用take()方法时会发生阻塞,直到有一个生产者生产了一个元素,同理生产者调用put()方法


LinkedBlockingDeque


使用双向队列实现的有界双端阻塞队列。双端意味着可以像普通队列一样FIFO也可以像栈一样FILO


LinkedTransferQueue


这是一个无界队列


拒绝策略

当线程池的线程达到最大线程数时,需要执行拒绝策略,拒绝策略需要实现RejectedExecutionHandler接口,并实现rejectedExcution方法,Executors为我们实现了4种拒绝策略


AbortPolicy(默认):丢弃任务并抛出异常

CallerRunsPolicy:由调用线程处理该任务

DiscardPolicy:丢弃任务,但是不抛出异常

DiscardOldestPolicy:丢弃队列中最早未处理的异常

e82d158a6ee04d3487c060ad73788716.jpeg


功能线程池


定长线程池(newFixedThreadPool)

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

特点 : 只有核心线程,线程数量固定,全是核心线程任务队列为链表的有界队列

应用场景: 控制线程最大并发数

缺点: 他的任务队列是LinkedBlockingQueue且没有指定容量,则当线程数满了之后就会一直放任务进任务队列,容易造成OOM


单线程化线程池(newSingleThreadExecutor)

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

特点:没有核心线程数只有非核心线程数,整个线程池表现为线程池数会根据任务量不断增长,没有增长,当任务执行完毕,空闲1分钟后释放线程

用途 :适合任务数比较密集,但每个任务执行时间较短的情况

缺点 : 如果任务多那么线程就会创建过多的线程,创建线程会很耗时并且容易导致OOM


定时线程池(newScheduledThreadPool)

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


特点: 和性能线程固定,非核心线程很多,执行完立即删除

应用场景: 执行定时或周期性的任务

缺点: 线程数量上限是Integer.MAX_VALUE


线程池中的方法

void execute(Runnable command);

执行任务


Future submit(Callable task)

提交任务task,用返回值Future获取任务执行结果


List<Future> invokeAll(Collection<? extends Callable> tasks)

提交tasks中所有的任务


List<Future> invokeAll(Collection<? extends Callable> tasks, long timeout, TimeUnit unit)

提交tasks中所有的任务带超时时间


T invokeAny(Collection<? extends Callable> tasks)

提交tasks中的任务那个先执行完毕返回该任务的结果其它任务取消


T invokeAny(Collection<? extends Callable> tasks,long timeout, TimeUnit unit)

提交tasks中的任务那个先执行完毕返回该任务的结果其它任务取消带超时时间


shutdown与shutdownnow


shutdown

线程池状态修改为SHUTDOWN

不会接收新的任务,但已提交的会执行完, 只打断空闲线程


shutdownnow

修改线程池状态为stop

不接收新任务、打断所有线程、会将队列中的任务返回


相关文章
|
3天前
|
设计模式 消息中间件 算法
【实习总结】Java学习最佳实践!
【实习总结】Java学习最佳实践!
22 3
|
3天前
|
数据采集 安全 Java
Java并发编程学习12-任务取消(上)
【5月更文挑战第6天】本篇介绍了取消策略、线程中断、中断策略 和 响应中断的内容
30 4
Java并发编程学习12-任务取消(上)
|
3天前
|
Java 数据库
【Java多线程】对线程池的理解并模拟实现线程池
【Java多线程】对线程池的理解并模拟实现线程池
16 1
|
3天前
|
Java
Java并发编程:深入理解线程池
【4月更文挑战第30天】本文将深入探讨Java并发编程中的一个重要主题——线程池。我们将从线程池的基本概念入手,了解其工作原理和优势,然后详细介绍如何使用Java的Executor框架创建和管理线程池。最后,我们将讨论一些高级主题,如自定义线程工厂和拒绝策略。通过本文的学习,你将能够更好地理解和使用Java的线程池,提高你的并发编程能力。
|
2天前
|
NoSQL 算法 Java
【redis源码学习】持久化机制,java程序员面试算法宝典pdf
【redis源码学习】持久化机制,java程序员面试算法宝典pdf
|
3天前
|
Java 调度
Java一分钟之线程池:ExecutorService与Future
【5月更文挑战第12天】Java并发编程中,`ExecutorService`和`Future`是关键组件,简化多线程并提供异步执行能力。`ExecutorService`是线程池接口,用于提交任务到线程池,如`ThreadPoolExecutor`和`ScheduledThreadPoolExecutor`。通过`submit()`提交任务并返回`Future`对象,可检查任务状态、获取结果或取消任务。注意处理`ExecutionException`和避免无限等待。实战示例展示了如何异步执行任务并获取结果。理解这些概念对提升并发性能至关重要。
18 5
|
3天前
|
Java 调度
Java并发编程:深入理解线程池
【5月更文挑战第11天】本文将深入探讨Java中的线程池,包括其基本概念、工作原理以及如何使用。我们将通过实例来解释线程池的优点,如提高性能和资源利用率,以及如何避免常见的并发问题。我们还将讨论Java中线程池的实现,包括Executor框架和ThreadPoolExecutor类,并展示如何创建和管理线程池。最后,我们将讨论线程池的一些高级特性,如任务调度、线程优先级和异常处理。
|
3天前
|
缓存 Java 数据库
Java并发编程学习11-任务执行演示
【5月更文挑战第4天】本篇将结合任务执行和 Executor 框架的基础知识,演示一些不同版本的任务执行Demo,并且每个版本都实现了不同程度的并发性。
34 4
Java并发编程学习11-任务执行演示
|
3天前
|
数据库连接
java+ssm+vue代码视频学习讲解
java+ssm+vue代码视频学习讲解
10 0