java种线程池多线程有返回值_JAVA备忘录(四):线程池面试题

本文详细介绍了Java线程池的概念、常见线程池类型及其适用场景,包括newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor和newScheduledThreadPool。还探讨了线程池的重要参数、拒绝策略、execute与submit的区别,以及线程池的工作队列和Future类的get方法。通过对线程池深入理解,有助于优化多线程处理并提升系统效率。
摘要由CSDN通过智能技术生成

一.什么是线程池?

首先说一下它的定义,线程池是一种多线程处理形式,当有任务提交到线程池时,可以直接使用线程池内的线程来执行任务。而如果不使用线程池的话,每次任务的执行都需要进行一次线程的创建于下销毁,这个过程的开销是比较大的,甚至超过了业务本身的执行开销。使用线程池就可以对这个问题进行优化。

JUC下的Executors类提供了Executor接口的实现方式用来创建线程池。

而线程池对象实际上是ThreadPoolExecutor对象;java本身也给我们封装好了几种常用的线程池。

二.说说几种常见的线程池及其使用场景

1.newFixedThreadPool:这是一个固定长度大小的线程池;当有新的任务提交且线程池中线程数还没达到最大值时,会不断创建新的线程到线程池中,直到达到最大值;超出的线程就会到任务阻塞队列中进行等待。用的是LinkedBlockingQueue这个任务阻塞队列。

适用于并发数量比较稳定的场景。

2 newCachedThreadPool:这是一个可缓存的线程池。容量有上限,可以在调用静态工厂方法时显式传入,而如果不传入参数的话,默认最大容量为Integer.MAX_VALUE。当任务所需线程数小于corePoolSize(核心线程数)时,直接在线程池创建新的线程;当所需线程大于corePoolSize时,当前任务就会进入任务拥塞队列之中;而所需线程数大于线程池最大容量且队列已满的时候,就会执行拒绝策略来处理。该线程池所使用的队列是SynchronizedQueue。并且启用TimeOut机制:当线程池中的非核心线程闲置超过60s时,该线程就会被销毁。

适用于线程数量多且执行时间短的场景。

3 newSingleThreadExecutor:单线程化的线程池,只有唯一的一个工作线程来执行任务,保证所有任务都能按照指定顺序(先来先服务,最高优先级等)来运行

4 newScheduledThreadPool:相比之下功能更强大,支持定时以及周期性任务的执行。

适用于需要进行定时或周期性任务的场景。

三.线程池的几个重要参数?

线程池的参数其实就是ThreadPoolExecutor类的参数。

1.corePoolSize就是线程池中的核心线程数量,这几个核心线程在闲置了特定的时间之后也不会被回收(当然也可以设定为会被回收)

2.maximumPoolSize:线程池中可以容纳的最大线程的数量。

3.keepAliveTime:非核心线程的最大空闲时间,空闲超过了这个时间的非核心线程会被自动回收

4.util:计算keepAliveTime的时间单位,如秒,毫秒。

5.workQueue:任务拥塞队列。当任务所需线程超过了线程池核心线程数时,任务就要进入队列中进行等待,一般是按照先来先服务的调度策略。

6.threadFactory:就是创建线程的线程工厂。

7.handler:拒绝策略。当线程池达到最大容量且队列满了之后,对于超额的任务的处理方法。

四.说说线程池的拒绝策略吧?

当任务提交到线程池,而线程池已经达到最大容量,且队列已满,此时就会对提交的任务拒绝服务,就是拒绝策略。RejectedExecutionHandler接口提供途径去自定义方法去实现拒绝策略。而在ThreadPoolExecutor中已经有四种拒绝策略了。

AbortPolicy:拒绝服务时直接抛出异常,阻止线程池的正常工作。

CallerRunPolicy:直接在调用者线程中运行当前的任务。

DiscardPolicy:直接将该方法丢弃,不进行处理。

DiscardOrdestPolicy:丢弃队列中最老的一个任务,并重新提交当前任务。

除此之外还可以根据实际需要自定义拒绝策略,只要实现RejectedExecutionHandler接口就可以了。

五.execute和submit的区别。

execute方法是线程池中最原生的方法,也是Executor接口中唯一一个方法,它可以接受Callable对象或者Runnable对象。而submit方法其实就是调用了execute方法,只能接受Callable对象。

最主要的区别在于execute方法执行线程没有返回值,而submit方法执行会返回一个Future类对象,通过该对象的get方法可以获取线程执行的返回值。另外Future类的get方法是阻塞操作,当submit多个Callable时,只有所有任务都执行完成了,才能使用get按照任务提交顺序依此获得返回值。

六.线程池有哪几种工作队列?

1.ArrayBlockingQueue:基于数组实现的有界阻塞队列,采取先进先出原则对元素进行排序。

2.LinkedBlockingQueue:基于链表实现的阻塞队列,也采用先进先出来排序元素,静态工厂方法创建的newFixedThreadPool()线程池就使用了这种队列。

3.SynchronousQueue:一个不储存元素的阻塞队列。特点为在当前任务进行插入同时,上一个进入队列的任务必须被移除,反之亦然;如果不满足这个条件,操作就会一直处于阻塞状态。静态工厂方法创建的newCachedThreadPool就用这种队列。

4.DelayedWorkQueue:类似于LinkedBlockingQueue,也是基于链表实现。但是元素排序方式是按照最高优先级来进行。

七.说一下Future类的get()方法?

当Callble对象作为参数被传入线程池的submit()方法进行执行时,方法会返回一个Future类对象,而Future对象的get方法可以获取到对应线程执行的返回值(也就是Callable对象call方法的返回值)。

需要提到的是,Future类的get方法是一个阻塞操作,也就是说只有当线程执行完毕并返回值之后,get方法才能获取到返回值,否则将一直阻塞直至线程执行完毕返回值。这样的话就会有资源浪费的情况发生,比如submit提交了一系列任务之后返回一系列Future对象,对Future对象逐个调用get方法可能会发生阻塞,所以可能造成一种情况比如后面的线程早已经执行完毕了,但此时还需要等待前面的线程执行完,才能获得到返回值。

解决方法主要有两个:

Future类中还有一个get的重载方法,该方法传入一个时间大小参数和一个时间单位参数,规定get方法最多只能阻塞有限的时间,超过有限时间将放弃接受返回值,退出阻塞。但这个方法有点治标不治本,因为本质上它还是要阻塞一段时间。

可以使用CompletionService类,该类的构造需要传入一个线程池对象作为参数。使用方法和线程池相同,也拥有submit()方法。和Future类不一样的是,CompletionService对象获取线程执行返回值的操作是不阻塞操作,也就是说它不关心get方法调用顺序,而是只要有线程执行完毕并且返回值,就可以直接获取到。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
颠覆你对线程池的认知。线程池可以多参还能带返回值, 使用简单到你不敢相信。传自定义型功能。传任意参功能。 re = 线程池1.创建 (任务_单参, 回调函数, 待机数, 最大数) '线程工作完。返回结果到回调函数线程池 工作线程返回值将返回到回调函数里面。可用来判断线程执行的结果。 re = 线程池1.销毁 (0, 0)  ' 。0=正常销毁(清空任务池,等待当前任务执行后返回 真) 1=强制销毁 re = 线程池1.投递任务 (i) re = 线程池2.投任务多整数参 (a, b, c, d, i)'.....可以无限多个 re = 线程池3.投任务多文本参 (a, b, c, d, 到文本 (i))'.....可以无限多个 线程池1.暂停 ()  ' 让线程池处于工作状态线程全部暂停。 线程池1.恢复 ()  ' 让线程池被暂停状态线程全部恢复工作。 线程池1.清空任务 ()  ' 清空未开始工作的任务,已开始工作的任务不受影响。 re = 线程池1.取状态 () ’0未创建或已销毁。1正在工作中。2空闲等待任务。3繁忙有任务正在排队。4正在销毁。 线程池1.刷新 () ‘刷新后取出 下面数据 排队线程总数 = 线程池1.排队线程总数 工作的线程数 = 线程池1.工作的线程数 剩余任务总数 = 线程池1.剩余任务总数 C版线程池,与C亲密接吻。 源码使用到shared_ptr,如果你是用VS2019可以直接改为std::shared_ptr, 出于易语言 VC6.0静态编译环境的需求,使用了boost 环境,用的版本号是boost_1_34_1。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值