189 8069 5689

JUC之线程池-创新互联

ThreadPoolExecutor 作用
  • 减少了线程创建和销毁的开销,当执行大量异步任务时线程池能提供较好的性能。

    创新互联专注于企业网络营销推广、网站重做改版、保亭黎族网站定制设计、自适应品牌网站建设、HTML5建站购物商城网站建设、集团公司官网建设、外贸营销网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为保亭黎族等各大城市提供网站开发制作服务。
  • 提供了一种资源限制和管理手段,比如可以限制线程的个数,动态新增线程等。
    在这里插入图片描述

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

  • ExecutorService接口继承了Executor,在其上做了一些shutdown()、submit()的扩展,可以说是真正的线程池接口;

  • AbstractExecutorService抽象类实现了ExecutorService接口中的大部分方法;

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

  • ScheduledExecutorService接口继承了ExecutorService接口,提供了带"周期执行"功能ExecutorService;

  • ScheduledThreadPoolExecutor是一个实现类,可以在给定的延迟后运行命令,或者定期执行命令。ScheduledThreadPoolExecutor比Timer更灵活,功能更强大。

状态
  • RUNNING:接受新任务并且处理阻塞队列里的任务。
  • SHUTDOWN:拒绝新任务但是处理阻塞队列里的任务。
  • STOP:拒绝新任务并且抛弃阻塞队列里的任务,同时会中断正在处理的任务。
  • TIDYING:所有任务都执行完(包含阻塞队列里面的任务)后当前线程池活动线程数为0,将要调用terminated方法。
  • TERMINATED:终止状态。terminated方法调用完成以后的状态。
线程池状态转换

线程池的核心参数
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueueworkQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
corePoolSize

线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize;
如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;
如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。

maximumPoolSize

线程池中允许的大线程数。如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize

keepAliveTime

线程空闲时的存活时间,即当线程没有任务执行时,继续存活的时间。默认情况下,该参数只在线程数大于corePoolSize时才有用

TimeUnit

keepAliveTime的时间单位

workQueue

workQueue必须是BlockingQueue阻塞队列。当线程池中的线程数超过它的corePoolSize的时候,线程会进入阻塞队列进行阻塞等待。通过workQueue,线程池实现了阻塞功能。
用于保存等待执行的任务的阻塞队列,一般来说,我们应该尽量使用有界队列,因为使用无界队列作为工作队列会对线程池带来如下影响。
1)当线程池中的线程数达到corePoolSize后,新任务将在无界队列中等待,因此线程池中的线程数不会超过corePoolSize。
2)由于1,使用无界队列时maximumPoolSize将是一个无效参数。
3)由于1和2,使用无界队列时keepAliveTime将是一个无效参数。
4)更重要的,使用无界queue可能会耗尽系统资源,有界队列则有助于防止资源耗尽,同时即使使用有界队列,也要尽量控制队列的大小在一个合适的范围。
所以我们一般会使用,ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue。

threadFactory

创建线程的工厂,通过自定义的线程工厂可以给每个新建的线程设置一个具有识别度的线程名,当然还可以更加自由的对线程做更多的设置,比如设置所有的线程为守护线程。
参见代码cn.enjoyedu.ch6. ThreadPoolAdvExecutors静态工厂里默认的threadFactory,线程的命名规则是“pool-数字-thread-数字”。

RejectedExecutionHandler

线程池的饱和策略,当阻塞队列满了,且线程数达到maximumPoolSize限制,如果继续提交任务,必须采取一种策略处理该任务,线程池提供了4种策略:
(1)AbortPolicy:直接抛出异常,默认策略;
(2)CallerRunsPolicy:用调用者所在的线程来执行任务;
(3)DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并将该任务添加至队列中;
(4)DiscardPolicy:直接丢弃任务;
当然也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,如记录日志或持久化存储不能处理的任务。

扩展线程池(线程池中的aop)

线程池中 beforeExecute和 afterExecute方法。相当于执行了一个切面。而在调用 shutdown 方法后则会调用 terminated 方法

提交任务

execute()方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功。
submit()方法用于提交需要返回值的任务。线程池会返回一个future类型的对象,通过这个future对象可以判断任务是否执行成功,并且可以通过future的get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,而使用get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完

合理地配置线程池

获取cpu核数 Runtime.getRuntime().availableProcessors();

CPU密集型任务(数据计算):Ncup+1
IO密集型任务(读取磁盘文件,读取数据库):2*Ncup
混合型任务:两者耗时相差两到三倍则拆分成两个线程池,偏差大的话就按大的处理

ScheduledThreadPoolExecutor

在指定一定延迟时间后或者定时进行调度执行的线程池

定时线程池中要进行捕捉异常,若不捕捉,程序会抛出异常不再执行并且程序无信息打印
ScheduledThreadPoolExecutor适用于需要多个后台线程执行周期任务,同时为了满足资源管理的需求而需要限制后台线程的数量的应用场景。
线程池队列使用DelayedWorkQueue; ScheduledFutureTask是具有返回值的任务,继承自FutureTask。FutureTask的内部有
一个变量state用来表示任务的状态。
ScheduledFutureTask内部还有一个变量period用来表示任务的类型,任务类型如下:

  • period=O,说明当前任务是一次性的,执行完毕后就退出了。
  • period为负数,说明当前任务为fxed-delay任务,是固定延迟的定时可重复执行任务。
  • period为正数,说明当前任务为fxed-rate任务,是固定频率的定时可重复执行任务。
常用方法 schedule(Runnable command,long delay,TimeUnit unit)

该方法的作用是提交一个延迟执行的任务,任务从提交时间算起延迟单位为unit的delay时间后开始执行。提交的任务不是周期性任务,任务只会执行一次。

scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit)

该方法的作用是,当任务执行完毕后,让其延迟固定时间后再次运行(fxed-delay任务)。其中initialDelay表示提交任务后延迟多少时间开始执行任务command,delay表示当任务执行完毕后延长多少时间后再次运行command任务,unit是initialDelay和delay的时间单位。任务会一直重复运行直到任务运行中抛出了异常,被取消了,或者关闭了线程池。

scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)

该方法相对起始时间点以固定频率调用指定的任务(fxed-rate任务)。当把任务提交到线程池并延迟initialDelay时间(时间单位为unit)后开始执行任务command。然后从initialDelay+period时间点再次执行,而后在initialDelay+2*period时间点再次执行,循环往复,直到抛出异常或者调用了任务的cancel方法取消了任务,或者关闭了线程池。scheduleAtFixedRate的原理与schedule WithFixedDelay类似,下面我们讲下它们之间的不同点。首先调用scheduleAtFixedRate的代码如下。

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


文章名称:JUC之线程池-创新互联
网页地址:http://cdxtjz.com/article/ccshoo.html

其他资讯