java中线程池的使用(ThreadPoolExecutor)

简介:

一.为什么使用线程池:

1.降低资源消耗。主要指的是降低创建和销毁线程时产生的cpu资源消耗,线程池通过持续工作的线程执行不断分配的新任务,来减少频繁的线程创建与销毁。

##2.提高响应速度。同上
##3.提高线程的可管理性。线程是稀缺资源,频繁的创建销毁,以及没有控制的大量创建,都会影响系统的稳定性。使用线程池可以统一分配,调优,监控资源。

二.如何创建线程池:

new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory,RejectedExecutionHandler handler);

corePoolSize:

线程池的基本大小,即在没有任务需要执行的时候线程池中运行的线程数量。只有在工作队列满了的情况下才会创建超出这个数量的线程。

相关1:

刚刚创建ThreadPoolExecutor的时候,线程并不会 立即启动,而是要等到有任务提交时才会启动。如果预先调用了prestartCoreThread()/prestartAllCoreThreads(),则会事先启动核心线程。

相关2:

考虑到keepAliveTime()和allowCoreThreadTimeOut()超市参数的影响,没有任务或者没有足够任务执行的时候,线程池中运行线程的数量(线程池的大小)小于等于corePoolSize。

maximumPoolSize:

线程池中允许的最大线程数,线程池中的当前运行线程数不会超过这个值,为了保证系统资源有控制的消耗。

相关1:

由于maximumPoolSize可以在运行中通过setMaximumPoolSize()来设置,所以可以通过largestPoolSize()方法来获得线程池曾经运行过的最大线程数量,来评估当前maximumPoolSize设置是否合适。

keepAliveTime:

当线程空闲后,保留的时间。用来在任务不繁忙的时候减少运行线程数量。在单任务时间较短,任务请求较频繁的情况下,可以适当延长保留存活时间来减少系统创建和销毁线程的开销。

相关1:

对于核心线程,默认一直保留存活,如果将allowCoreThreadTimeOut设置为true,则核心线程也接受keepAliveTime的约束。

TimeUnit unit:

用来修饰keepAliveTime的时间单位,可以为纳秒,毫秒,秒,分,小时,天等TimeUnit中的静态常量。

BlockingQueue:

线程安全的队列,用来存放排队的任务。

相关1:

此BlockingQueue的实现有:
->ArrayBlockingQueue:基于数组结构的有届阻塞队列,FIFO
->LinkedBlockingQueue:基于链表的阻塞队列,FIFO。吞吐量大于上者。静态工厂方法Executors.newFixedThreadPool()使用了这个队列
->SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量高于LinkedBlockingQueue.静态工厂方法Executors.newCachedThreadPool()使用了这个队列。
->PriorityBlockingQueue:一个具有优先级的无限阻塞队列。

ThreadFactory:

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

RejectedExecutionHandler:

当队列和线程池都满了之后的饱和策略。默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。以下是JDK1.5提供的四种策略:
->AbortPolicy:直接抛出异常
->CallerRunsPolicy:只用调用者所在的线程来运行任务。
->DiscardOldestPolicy:丢弃队列里最近一个任务,并执行当前任务。
->DiscardPolicy:不处理,丢弃掉。
->也可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略。如记录日志或持久化不能处理的任务。

三.如何调用线程池:

1.通过execute(Runnable run)方法来执行任务:

threadsPool.execute(new Runnable(){

@override
public void run(){
    //code to run.
}

});
但是execute()方法没有返回值,无法获得任务执行的情况信息。

2.通过submit()方法来提交执行任务:

Future future=executor.submit(harReturnValueTask);
try{

Object o=future.get();

}catch(Exeception e){

}finally{

executor.shutdown();

}
submit()方法会返回一个future对象,通过future的get()方法,可以获得任务执行情况。get()方法会阻塞直到任务执行完毕。也可以使用get(long timeout, TimeUnit unit)来设置最长阻塞时间。

如何关闭线程池:

我们可以通过调用线程池的shutdown或shutdownNow方法来关闭线程池,它们的原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务可能永远无法终止。但是它们存在一定的区别,shutdownNow首先将线程池的状态设置成STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表,而shutdown只是将线程池的状态设置成SHUTDOWN状态,然后中断所有没有正在执行任务的线程。
只要调用了这两个关闭方法的其中一个,isShutdown方法就会返回true。当所有的任务都已关闭后,才表示线程池关闭成功,这时调用isTerminaed方法会返回true。至于我们应该调用哪一种方法来关闭线程池,应该由提交到线程池的任务特性决定,通常调用shutdown来关闭线程池,如果任务不一定要执行完,则可以调用shutdownNow。

今天困了,先写到这里,主要参考文章:
http://blog.csdn.net/scboyhj__/article/details/48805881

相关文章
|
4天前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
4天前
|
存储 监控 安全
一天十道Java面试题----第三天(对线程安全的理解------>线程池中阻塞队列的作用)
这篇文章是Java面试第三天的笔记,讨论了线程安全、Thread与Runnable的区别、守护线程、ThreadLocal原理及内存泄漏问题、并发并行串行的概念、并发三大特性、线程池的使用原因和解释、线程池处理流程,以及线程池中阻塞队列的作用和设计考虑。
|
2天前
|
存储 缓存 安全
深度剖析Java HashMap:源码分析、线程安全与最佳实践
深度剖析Java HashMap:源码分析、线程安全与最佳实践
|
3天前
|
缓存 前端开发 JavaScript
一篇文章助你搞懂java中的线程概念!纯干货,快收藏!
【8月更文挑战第11天】一篇文章助你搞懂java中的线程概念!纯干货,快收藏!
10 0
一篇文章助你搞懂java中的线程概念!纯干货,快收藏!
|
2天前
|
算法 安全 Java
深入解析Java多线程:源码级别的分析与实践
深入解析Java多线程:源码级别的分析与实践
|
3天前
|
Java 程序员 调度
深入浅出Java多线程编程
Java作为一门成熟的编程语言,在多线程编程方面提供了丰富的支持。本文将通过浅显易懂的语言和实例,带领读者了解Java多线程的基本概念、创建方法以及常见同步工具的使用,旨在帮助初学者快速入门并掌握Java多线程编程的基础知识。
3 0
|
3天前
|
Java
java中获取当前执行线程的名称
这篇文章介绍了两种在Java中获取当前执行线程名称的方法:使用`Thread`类的`getName`方法直接获取本线程的名称,以及使用`Thread.currentThread()`方法获取当前执行对象的引用再调用`getName`方法。
|
3天前
|
Java 测试技术
Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
9 0
|
4天前
|
Java
Java多线程-死锁的出现和解决
死锁是指多线程程序中,两个或以上的线程在运行时因争夺资源而造成的一种僵局。每个线程都在等待其中一个线程释放资源,但由于所有线程都被阻塞,故无法继续执行,导致程序停滞。例如,两个线程各持有一把钥匙(资源),却都需要对方的钥匙才能继续,结果双方都无法前进。这种情况常因不当使用`synchronized`关键字引起,该关键字用于同步线程对特定对象的访问,确保同一时刻只有一个线程可执行特定代码块。要避免死锁,需确保不同时满足互斥、不剥夺、请求保持及循环等待四个条件。
|
Java 安全 数据库
java多线程系列:ThreadPoolExecutor源码分析
前言 这篇主要讲述ThreadPoolExecutor的源码分析,贯穿类的创建、任务的添加到线程池的关闭整个流程,让你知其然所以然。希望你可以通过本篇博文知道ThreadPoolExecutor是怎么添加任务、执行任务的,以及延伸的知识点。
1180 0