您的位置:首页 > 编程语言 > Java开发

线程池相关

2018-08-19 13:17 357 查看
在java.util.concurrent包下,提供了一系列与线程池相关的类。

使用线程池的好处

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

提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行;

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

线程池可以应对突然大爆发量的访问,通过有限个固定线程为大量的操作服务,减少创建和销毁线程所需的时间。

线程池相关类的继承关系



使用线程池的方式

我们一般通过工具类Executors的静态方法来获取线程池:

通过newFixedThreadPool()来获取ThreadPoolExecutor线程池

通过newScheduledThreadPool()来获取ScheduleThreadPoolExecutor线程池

如下使用:

ExecutorService threadpool = Executors.newFixedThreadPool(10);

我们指定了获取10个数量的固定线程池,Executors中有很多重载的获取线程池的方法,比如可以通过自定义的ThreadFactory来为每个创建出来的Thread设置更为有意义的名称。Executors创建线程池的方法内部也就是new出新的ThreadPoolExecutor或ScheduleThreadPoolExecutor,给我们配置了很多默认的设置。

线程池的参数

corePoolSize(线程池的基本大小):当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThreads方法,线程池会提前创建并启动所有基本线程。

maximumPoolSize(线程池最大大小):线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。值得注意的是如果使用了无界的任务队列这个参数就没什么效果。

keepAliveTime(线程活动保持时间):线程池的工作线程空闲后,保持存活的时间。所以如果任务很多,并且每个任务执行的时间比较短,可以调大这个时间,提高线程的利用率。

TimeUnit(线程活动保持时间的单位):可选的单位有天(DAYS),小时(HOURS),分钟(MINUTES),毫秒(MILLISECONDS)等。

workQueue(任务队列):用于保存等待执行的任务的阻塞队列。 可以选择以下几个阻塞队列:ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue

threadFactory:用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字。

handler(饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。

我们尽量优先使用Executors提供的静态方法来创建线程池,如果Executors提供的方法无法满足要求,再自己通过ThreadPoolExecutor类来创建线程池

提交任务的两种方式

通过execute()方法这种方式提交没有返回值,也就不能判断任务是否被线程池执行成功

通过submit()方法它会返回一个Future对象,通过future的get方法来获取返回值,get方法会阻塞住直到任务完成,而使用get(long timeout, TimeUnit unit)方法则会阻塞一段时间后立即返回,这时有可能任务没有执行完。

线程池工作流程



从上图我们可以看出,当提交一个新任务到线程池时,线程池的处理流程如下:

首先线程池判断核心线程池是否已满(< corePoolSize ?)没满,创建一个工作线程来执行任务。满了,则进入下个流程。

其次线程池判断工作队列是否已满?没满,则将新提交的任务存储在工作队列里,等待核心线程池的线程空闲以后来执行。满了,则进入下个流程。

最后线程池判断整个线程池是否已满(< maximumPoolSize ?)没满,则创建一个新的工作线程来执行任务,满了,则交给饱和策略来处理这个任务。

也就是说,线程池优先要创建出核心线程池大小(corePoolSize)的线程数量,没有达到这个数量时,每次提交新任务都会直接创建一个新线程,当达到了基本线程数量后,又有新任务到达,优先放入等待队列,如果队列满了,才去创建新的线程(不能超过线程池的最大数maxmumPoolSize)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  threadpool Java