【java并发】Executor框架详解

Java并发——Executor框架详解

一、Executor框架概念

我们知道线程池就是线程的集合,线程池集中管理线程,以实现线程的重用,降低资源消耗,提高响应速度等。线程用于执行异步任务,单个的线程既是工作单元也是执行机制,从JDK1.5开始,为了把工作单元与执行机制分离开,Executor框架诞生了,他是一个用于统一创建与运行的接口。Executor框架实现的就是线程池的功能。

二、Executor框架结构详解

2.1 Executor框架

(1)任务。也就是工作单元,包括被执行任务需要实现的接口:Runnable接口或者Callable接口;

(2)任务的执行。也就是把任务分派给多个线程的执行机制,包括Executor接口及继承自Executor接口的ExecutorService接口。

(3)异步计算的结果。包括Future接口及实现了Future接口的FutureTask类。

Executor框架的成员及其关系可以用一下的关系图表示:

在这里插入图片描述

2.2 类与接口简介:
  • Executor是一个接口,它是Executor框架的基础,它将任务的提交与任务的执行分离开来

  • ThreadPoolExecutor是线程池的核心实现类,用来执行被提交的任务

  • ScheduledThreadPoolExecutor是一个实现类,可以在给定的延迟后运行命令,或者定期执行命令

  • Future接口和实现Future接口的FutureTask类代表异步计算的结果

  • Runnable接口和Callable接口的实现类,都可以被ThreadPoolExecutor或ScheduleThreadPoolExecutor执行

2.3 Executor框架成员

主要成员:ThreadPoolExecutor、ScheduleThreadPoolExecutor、Future接口、Runnable接口、Callable接口、Executors(工具类)

2.3.1 TheadPoolExecutor

ThreadPoolExecutor通常使用工厂类Executors来创建。Executors可以创建3种类型的ThreadPoolExecutor类:FixedThreadPool、SingleThreadExecutor、CachedThreadPool

  • FixedThreadPool:创建使用固定线程数的线程池; 适用于为了满足资源管理的需求,而需要限制当前线程数量的应用场景,它适用于负载比较重的服务器;

  • SingleThreadExecutor:创建使用单个线程的线程池; 适用于需要保证顺序的执行各个任务,并且在任意时间点,不会有多个线程是活动的应用场景;

  • CachedThreadPool:创建一个会根据需要创建新线程的线程池; 适用于执行很多的短期异步任务的小程序或者是负载比较轻的服务器;

2.3.2 ScheduledThreadPoolExecutor

ScheduleThreadPoolExecutor通常使用工厂类Executors来创建。Executors可以创建3种类型的ScheduleThreadPoolExecutor类:

  • ScheduleThreadPoolExecutor:创建固定个数线程的线程池; 适用于需要多个后台线程执行周期任务,同时为了满足资源管理的要求而需要限制后台线程的数量的引用场景;

  • SingleThreadScheduleExecutor:适用于需要单个后台线程执行周期任务,同时需要保证顺序的执行各个任务的场景

2.3.3 Future接口

Future接口和实现Future接口的FutureTask类用来表示异步计算的结果。当我们把Runnable接口或者Callable接口的实现类通过 submit 方法提交给线程池后,线程池会返回给我们一个FutureTask对象;

2.3.4 Runnable和Callable接口

Runnable接口和Callable接口的实现类,都可以被线程池执行。 它们之间的区别是Runnable不会返回结果,而Callable可以返回结果(体现在run方法上;另外:如果使用了Callable创建任务,那么线程池需要使用submit执行任务,不能使用execute)

除了自己可以创建Callable接口的对象外,我们还可以通过Executors工具类,将Runnable封装成一个Callable:

  • 把一个Runnable包装成一个Callable:submit之后,通过FutureTask.get()方法获取到的结果为null

  • 把一个Runnable和一个待返回结果(T)包装成Callable:submit之后,通过FutureTask.get()方法获取到的结果为T

三、ThreadPoolExecutor详解

Executor框架最核心的类是ThreadPoolExecutor,它是线程池的实现类,主要由下面4个组件构成:

  • corePool:核心线程池的大小

  • maximumPool:最大线程池的大小

  • BlockingQueue:用来暂时保存任务的工作队列

  • RejectedExecutionHandler:当ThreadPoolExecutor已经关闭或ThreadPoolExecutor已经饱和时(达到了最大线程池大小且队列已满),execute()方法将要调用Handler

3.1 FixedThreadPool详解
public static ExecutorService newFixedThreadPool(int nThreads){
   return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLSECONDS, new LinkedBlockingQueue<Runnable>());
}

FixedThreadPool使用无界队列 LinkedBlockingQueue 作为线程池工作队列(队列的容量为Integer.MAX_VALUE)。使用无界队列为工作队列会对线程池带来如下影响:

  • 当线程池中的线程数达到corePoolSize后,新任务将会在无界队列中等候,因此线程中的线程数不会超过corePoolSize

  • 由于1,使用无界队列时maximumPoolSize将是一个无效参数

  • 由于1和2,使用无界队列时keepAliveTime将是一个无效参数

  • 由于使用无界队列,运行中的FixedThreadPool不会拒绝任务

3.2 SingleThreadExecutor详解

SingleThreadExecutor是使用单个worker线程的Executor。

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

该线程池中的corePoolSize与maximumPoolSize均设置为1 ,保证每个时刻只有一个线程在运行

3.3 CachedThreadPool详解

CachedThreadPool是一个会根据需要创建新线程的线程池。

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

corePoolSize被设置为0,即corePoolSize为空;maximum被设置为Integer.MAX_VALUE,则认为是无界的

四、ScheduledThreadPoolExecutor详解

ScheduledThreadPoolExecutor继承自ThreadPoolExecutor,它主要用于在给定的延迟之后运行任务或者定期执行任务;

ScheduledThreadPoolExecutor会把待调度的任务放到一个DelayQueue队列中;

执行步骤:

  • 线程1从DelayQueue中获取到已到期的ScheduledFutureTask(DelayQueue.take())

  • 线程1执行这个ScheduledFutureTask

  • 线程1修改ScheduledFutureTask的time变量为下次将要被执行的时间

  • 线程1把修改time后的ScheduledFutureTask放回到DelayQueue中,等待下次执行

五、FutureTask

5.1 简介

FutureTask除了实现Future接口之外,还实现了Runnable接口。因此,FutureTask可以交给Executor执行,也可以由调用线程直接执行(FutureTask.run());

5.2 使用

可以把FutureTask交给Executor执行;

也可以通过ExecutorService.submit()方法返回一个FutureTask,然后执行FuntureTask.get()或者cancel()方法;

除此之外,还可以单独使用FutureTask

5.3 实现

FutureTask的实现基于AbstrackQueuedSynchronizer(简称:AQS)。

AQS是一个同步框架,它提供通用机制来原子性管理同步状态、阻塞和唤醒线程,以及维护被阻塞线程的队列; 基于AQS实现的同步器包括:ReentrantLock、ReentrantReadWriteLock、CountDownLatch和FutureTask;

每一个基于AQS实现的同步器都会包括两个类型的操作:

  • 至少一个acquire操作。这个操作阻塞调用线程,除非/直到AQS的状态允许这个线程继续执行。FutureTask的acquire操作为get()、get(long timeout, TimeUnit unit) 方法

  • 至少一个release操作。这个操作改变AQS的状态,改变后的状态可允许一个或者多个阻塞线程被解除阻塞。FutureTask的release操作包括run()方法和cancek()方法

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1节你真的了解并发吗? [免费观看][免费观看] 00:27:48分钟 | 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个阶段并推荐学习并发的资料 [免费观看] 00:09:13分钟 | 第5节线程的状态以及各状态之间的转换详解00:21:56分钟 | 第6节线程的初始化,中断以及其源码讲解00:21:26分钟 | 第7节多种创建线程的方式案例演示(一)带返回值的方式00:17:12分钟 | 第8节多种创建线程的方式案例演示(二)使用线程池00:15:40分钟 | 第9节Spring对并发的支持:Spring的异步任务00:11:10分钟 | 第10节使用jdk8提供的lambda进行并行计算00:14:22分钟 | 第11节了解多线程所带来的安全风险00:13:16分钟 | 第12节从线程的优先级看饥饿问题00:18:42分钟 | 第13节从Java字节码的角度看线程安全性问题00:25:43分钟 | 第14节synchronized保证线程安全的原理(理论层面)00:13:59分钟 | 第15节synchronized保证线程安全的原理(jvm层面)00:25:03分钟 | 第16节单例问题与线程安全性深入解析00:27:15分钟 | 第17节理解自旋锁,死锁与重入锁00:24:58分钟 | 第18节深入理解volatile原理与使用00:28:30分钟 | 第19节JDK5提供的原子类的操作以及实现原理00:27:10分钟 | 第20节Lock接口认识与使用00:19:54分钟 | 第21节手动实现一个可重入锁00:26:31分钟 | 第22节AbstractQueuedSynchronizer(AQS)详解00:49:04分钟 | 第23节使用AQS重写自己的锁00:31:04分钟 | 第24节重入锁原理与演示00:12:24分钟 | 第25节读写锁认识与原理00:18:04分钟 | 第26节细读ReentrantReadWriteLock源码00:30:38分钟 | 第27节ReentrantReadWriteLock锁降级详解00:13:32分钟 | 第28节线程安全性问题简单总结00:15:34分钟 | 第29节线程之间的通信之wait/notify00:32:12分钟 | 第30节通过生产者消费者模型理解等待唤醒机制00:20:50分钟 | 第31节Condition的使用及原理解析00:17:40分钟 | 第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟 | 第35节线程之间通信之join应用与实现原理剖析00:10:17分钟 | 第36节ThreadLocal 使用及实现原理00:17:41分钟 | 第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52分钟 | 第39节并发工具类Semaphore详解00:17:27分钟 | 第40节并发工具类Exchanger详解00:13:47分钟 | 第41节CountDownLatch,CyclicBarrier,Semaphore源码解析00:29:57分钟 | 第42节提前完成任务之FutureTask使用00:11:43分钟 | 第43节Future设计模式实现(实现类似于JDK提供的Future)00:19:20分钟 | 第44节Future源码解读00:29:22分钟 | 第45节Fork/Join框架详解00:28:09分钟 | 第46节同步容器与并发容器00:18:44分钟 | 第47节并发容器CopyOnWriteArrayList原理与使用00:15:52分钟 | 第48节并发容器ConcurrentLinkedQueue原理与使用00:31:03分钟 | 第49节Java中的阻塞队列原理与使用00:26:18分钟 | 第50节实战:简单实现消息队列00:11:07分钟 | 第51节并发容器ConcurrentHashMap原理与使用00:38:22分钟 | 第52节线程池的原理与使用00:42:49分钟 | 第53节Executor框架详解00:36:54分钟 | 第54节实战:简易web服务器(一)00:55:34分钟 | 第55节实战:简易web服务器(二)00:24:36分钟 | 第56节JDK8的新增原子操作类LongAddr原理与使用00:17:45分钟 | 第57节JDK8新增锁StampedLock详解00:29:37分钟 | 第58节重排序问题00:23:19分钟 | 第59节happens-before简单概述00:15:17分钟 | 第60节锁的内存语义00:13:54分钟 | 第61节volatile内存语义00:12:04分钟 | 第62节final域的内存语义00:34:07分钟 | 第63节实战:问题定位00:07:48分钟 |
### 回答1: 好的,我来给您讲解一下Java中的Executor框架。 在Java中,Executor框架是一种用于管理线程的高级工具。该框架允许开发者使用高级的API来管理线程,而无需直接使用底层线程管理机制。 Executor框架中的主要接口是ExecutorExecutorService。Executor接口定义了一个用于执行任务的方法,而ExecutorService则是一个扩展了Executor接口的接口,它提供了一系列管理任务和线程的方法,如提交任务、关闭线程池等。 在Executor框架中,任务被封装为实现了Runnable接口或Callable接口的对象。其中,Runnable接口表示一个没有返回值的任务,而Callable接口则表示一个可以返回结果的任务。这些任务被提交给线程池执行,线程池中的线程会从任务队列中获取任务并执行。 Executor框架提供了多种不同类型的线程池,如FixedThreadPool、CachedThreadPool、SingleThreadPool等。其中,FixedThreadPool是一个固定大小的线程池,CachedThreadPool是一个可以自动扩容的线程池,而SingleThreadPool则是一个只有一个线程的线程池。 除了线程池之外,Executor框架还提供了一些其他的工具类,如ScheduledExecutorService用于定时执行任务、CompletionService用于管理异步任务等。 总的来说,Executor框架是一个非常实用的线程管理工具,它简化了线程管理的复杂性,并提供了多种线程池和工具类,帮助开发者更加方便地管理线程。 ### 回答2: Executor框架Java提供的一个用于管理和调度线程的高级框架。它在java.util.concurrent包下,提供了一组接口和类来处理线程的创建、启动、执行和调度。 Executor框架主要包含了三个核心组件:ExecutorExecutorService和ThreadPoolExecutor。 首先,Executor是一个接口,它定义了一个简单的方法execute(Runnable command),用于执行传入的任务。它隐藏了线程的创建和启动过程,只需要将任务交给Executor,它会在后台自动创建线程并执行任务。 其次,ExecutorService是一个接口,它继承自Executor接口,并增加了一些管理和控制线程的方法。它提供了submit(Callable task)方法,用于提交有返回值的任务,并返回一个Future对象,可以通过该对象获取任务的执行结果。ExecutorService还提供了shutdown()和shutdownNow()方法,用于优雅地停止线程池的运行。 最后,ThreadPoolExecutorExecutorService接口的一个实现类。它实现了一个基于线程池的ExecutorService,可以根据任务的数量和需要的资源动态地创建、回收和管理线程。ThreadPoolExecutor通过内部的任务队列和线程池来实现任务的调度和执行。可以通过调整线程池的参数来控制并发执行的线程数量和线程的优先级。 Executor框架的使用可以提供多线程编程的简化和优化。它可以将任务的提交和执行进行分离,将任务的执行交给线程池管理,从而充分复用线程资源,避免线程创建和销毁的开销。同时,它还提供了任务的调度和控制功能,可以根据需要在多个线程之间进行任务的切换和调度,提高系统的运行效率和资源利用率。 总结来说,在Java中,Executor框架是一个强大的并发编程工具,通过它我们可以方便地管理和控制线程的执行,提高程序的性能和响应速度。 ### 回答3: Executor框架Java中用于管理和调度线程的一个重要框架。它提供了一种简单且高效的方式来执行异步任务,并且能够更好地管理线程池资源。 Executor框架提供了一个Executor接口,该接口定义了一个线程池的基本执行操作。常见的实现类有ThreadPoolExecutor和ScheduledThreadPoolExecutor,它们都是Executor接口的具体实现。 通过Executor框架,我们可以使用线程池执行任务,从而避免了为每个任务创建新线程带来的开销。我们只需要将任务提交给线程池即可,线程池会自动进行线程的创建和管理,实现任务的异步执行。 Executor框架还提供了一些功能丰富的方法,如submit()方法和invokeAll()方法。submit()方法用于提交一个任务并返回一个表示该任务结果的Future对象,我们可以利用Future对象来获取任务的执行结果或取消任务的执行。invokeAll()方法用于同时提交多个任务,并等待所有任务完成。 除了常规的线程池功能外,Executor框架还引入了一些用于定时任务调度的类,例如ScheduledThreadPoolExecutor和ScheduledExecutorService。这些类可以实现任务的定时执行、周期执行以及延迟执行等功能。 总之,Executor框架Java中管理和调度线程的重要工具。它提供了一种高效的线程池资源管理方式,并且提供了一些方便的方法来操作和管理任务的执行。在实际开发中,合理地使用Executor框架可以提高程序的性能和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值