阻塞队列和线程池原理

阻塞队列 实现了BlockingQueue接口

 

阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。阻塞队列就是生产者用来存放元素、消费者用来获取元素的容器。

 

阻塞队列优点:充当一个容器来解决生产者和消费者的强耦合问题,平衡生产线程和消费线程的工作能力来提高程序整体处理数据的速度

生产者和消费者彼此之间不直接通信,而是通过阻塞队列来进行通信,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

 

阻塞队列的阻塞的两种方式

当阻塞队列满时,生产者线程想继续往队列放元素时会阻塞;阻塞队列为空时,消费者队列想从队列中去元素时会阻塞

 

 

使用线程池的优势

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

第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。   如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能。线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提高服务器程序性能的。它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。

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

 

线程池的类关系

 

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

ExecutorService接口继承了Executor,可以说是真正的线程池接口

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

 

创建ThreadPoolExecutor时传入的各个参数

 

 

corePoolSize

线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize;

如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;

如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。

 

maximumPoolSize

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

 

keepAliveTime

线程空闲时的存活时间,即当线程没有任务执行时,继续存活的时间。

 

workQueue

阻塞队列,当线程池中的线程数超过它的corePoolSize的时候,线程会进入阻塞队列进行阻塞等待。通过workQueue,线程池实现了阻塞功能。

 

 

线程池的工作机制

1.如果当前运行的线程少于corePoolSize,则创建新线程来执行任务

2.线程数量等于或多余corePoolSize,将新任务放入阻塞队列

3.如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任务。

4.如果创建新线程将使当前运行的线程超出maximumPoolSize,任务将被拒绝,并调用RejectedExecutionHandler.rejectedExecution()方法。

 

四种拒绝处理的方式

 

 

提交任务

往线程池中提交任务有两种方式,可以传入一个实现了runable或callable的类

1.execute()方法,传入一个实现了runable接口的类

2.submit()方法用于提交需要返回值的任务。线程池会返回一个future类型的对象,通过这个future对象可以判断任务是否执行成功,并且可以通过future的get()方法来获取返回值

 

线程池的关闭

调用shutdown或shutdownNow

它们的原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务可能永远无法终止,我们开发者需要手动对interrupt中断变量进行判断,进行相应的操作。shutdownNow首先将线程池的状态设置成STOP,然后中断所有的正在执行或暂停任务的线程,而shutdown是将线程池的状态设置成SHUTDOWN状态,中断所有没有正在执行任务的线程。

 

 

性质不同的任务可以用不同规模的线程池分开处理。

CPU密集型任务应配置尽可能小的线程,如配置Ncpu+1个线程的线程池。由于IO密集型任务线程并不是一直在执行任务,则应配置尽可能多的线程,如2*Ncpu。

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值