首页 > 编程知识 正文

java多线程返回结果汇总,多线程与线程池的运用

时间:2023-05-05 03:44:24 阅读:146696 作者:2211

一.什么是线程池?

首先介绍其定义,线程池是一种多线程处理格式,在将任务提交到线程池时,可以直接使用线程池中的线程来执行任务。 如果不使用线程池,则必须在每次执行任务时创建和销毁线程。 这个过程的开销比较大,超过了业务本身的执行开销。 线程池允许您优化此问题。

JUC下的Executors类提供了一种实现用于创建线程池的Executor接口的方法。

线程池对象实际上是一个线程池执行程序对象。 java本身也封装了一些常用的线程池。

2 .说几个常见的线程池及其使用场景

1.newFixedThreadPool :这是固定长度的线程池。 如果提交了新任务,并且线程池中的线程数未达到最大值,则线程将继续在线程池中创建,直到达到最大值。 超过的线程时,等待任务块队列。 正在用一个名为LinkedBlockingQueue的任务阻止队列。

适用于同时数比较稳定的场景。

2 newCachedThreadPool :这是一个可缓存的线程池。 容量有上限,可以在调用静态工厂方法时显式传递。 如果不传递参数,则缺省最大容量为Integer.MAX_VALUE。 如果任务所需的线程数少于corePoolSize,则直接在线程池中创建新线程; 如果所需线程大于corePoolSize,则当前任务将进入任务拥塞队列。 如果所需线程数超过线程池的最大容量,且队列已满,则执行拒绝策略。 线程池使用的队列是同步队列。 启用TimeOut机制。 如果线程池中的非核心线程空闲超过60s,则线程将被销毁。

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

3 newSingleThreadExecutor (单线程线程池。 只有唯一的工作线程执行任务,并确保所有任务都按照指定的顺序(首先提供服务,然后按最高优先级等)执行

4 newScheduledThreadPool :比它更强大,支持定时和周期性任务的执行。

适合需要定时或周期性任务的场景。

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

线程池的参数实际上是ThreadPoolExecutor类的参数。

1.corePoolSize是线程池中的核心线程数,即使在特定时间空闲后也不会回收这些核心线程。 当然也可以设定为被回收。

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

3.keepAliveTime :无核心线程的最大空闲时间。 空闲时间超过此时间的无核心线程将自动回收

4.util :计算关键时间的时间单位,例如秒和毫秒。

5 .工作队列:任务拥塞队列。 如果任务所需的线程超过线程池的核心线程数,任务将排队等待。 通常遵循首先提供服务的时间表策略。

6.threadFactory :用于创建线程的线程工厂。

7.handler :拒绝策略。 线程池达到最大容量且队列已满后,如何处理超额任务。

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

如果任务已提交到线程池,线程池已达到最大容量,且队列已满,则针对已提交的任务拒绝服务。 也就是说,策略被拒绝。 RejectedExecutionHandler接口提供了一种定制实现拒绝策略的方法。 在ThreadPoolExecutor中已经有四种拒绝策略。

AbortPolicy拒绝服务时直接抛出异常,阻止线程池正常运行。

CallerRunPolicy :直接在被调用线程上执行当前任务。

DiscardPolicy :直接销毁此方法,不处理。

DiscardOrdestPolicy :放弃队列中最旧的任务并重新发送当前任务。

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

五.执行和提交的区别。

execute方法是线程池中最本机的方法,也是Executor接口中唯一的方法,可以接受Callable对象或Runnable对象。 submit方法实际上调用execute方法,只能接受Callable对象。

最大的区别在于,执行execute方法的线程没有返回值,而执行submit方法返回一个Future类对象,该对象可以检索线程执行的返回值。 此外,Future类的get方法是一个阻塞操作,如果提交了多个Callable,则只有在所有任务都完成时,才能使用get按任务提交的顺序获取返回值。

6 .线程池中有多少种工作队列?

1.ArrayBlockingQueue :根据数组实现的有界闭塞队列,采用先进先出原则对元素进行排序。

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

3 .同步队列

ue:一个不储存元素的阻塞队列。特点为在当前任务进行插入同时,上一个进入队列的任务必须被移除,反之亦然;如果不满足这个条件,操作就会一直处于阻塞状态。静态工厂方法创建的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方法调用顺序,而是只要有线程执行完毕并且返回值,就可以直接获取到。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。