首页 > 编程语言 > 详细

JDK线程池详解

时间:2016-03-31 02:22:51      阅读:246      评论:0      收藏:0      [点我收藏+]

一:线程池的原理
?? 对于异步或者有大量并发执行任务的程序来说,使用线程池可以有效降低资源,提高程序的响应速度。对于如何最大化的利用线程池,做到资源统一分配,调优,就必须了解线程池的原理。
1.1 线程池的实现原理
????? 当一个任务提交给线程池后,线程池会有如下的处理流程:
?? 1) 判断线程池里的核心线程是否有空闲,如果有空闲,则创建一个新的线程来执行任务。
?? 2) 在不满足一的前提下,任务会被加入的等待队列,如果等待队列没有满,则将任务加入到队列里面,如果满了,则进行下一个流程。
?? 3) 判断最大线程数是否已经满了,如果没满,则创建一个核心线程来处理任务,如果满了,则根据不同的拒绝策略拒绝任务的执行。
?? 大概的流程如下图:

bubuko.com,布布扣
?
二:线程池的创建
????? 我们可以通过ThreadPoolExecutor来创建一个线程池
? public ThreadPoolExecutor(int corePoolSize,
????????????????????????????? int maximumPoolSize,
????????????????????????????? long keepAliveTime,
????????????????????????????? TimeUnit unit,
??????????????????????????? BlockingQueue<Runnable> workQueue)
?? corePoolSize:线程池的基本大小,当提交一个新任务时,如果没有超过corePoolSize设置的大小,会创建一个新任务来执行,即使此时存在空闲的线程
?? maximumPoolSize:线程池最大数量,当队列满的时候,如果还未超过maximumPoolSize设置的值,则会创建新线程来执行。
?? keepAliveTime:空闲线程存活时间,如果超过了设置的时间,线程会被回收。
?? TimeUnit:一个枚举类,主要用来设置保持线程活动时间的单位。
?? workQueue: 任务队列,用来保存等待执行的任务,有很多种阻塞队列,比如ArrayBlockingQueue,LinkdedBlockingQueue等。
三:线程池提交任务
? 我们可以使用execute()和submit()提交任务。
?3.1 使用execute()提交任务
??? poolExecutor.execute(new Runnable() {
??? ??? ??? ??? @Override
??? ??? ??? ??? public void run() {
??? ??? ??? ??? ??? System.out.println("线程池运行");
??? ??? ??? ??? }
??? ??? ??? });
?3.2 使用submit()提交任务
??? ExecutorService service =?? Executors.newCachedThreadPool();
??? Future<String> future = service.submit(new Callable<String>() {
??? ??? ??? @Override
??? ??? ??? public String call() throws Exception {
??? ??? ??? ??? return "result";
??? ??? ??? }
??? ??? });
??? System.out.println(future.get());
四:阻塞队列
?? 在使用ThreadPoolExecutor创建一个线程池的时候,需要传一个BlockingQueue<Runnable>,用于保存等待的任务,下面介绍常用的几种阻塞队列。
? 4.1 ArrayBlockingQueue
?? ArrayBlockingQueue是一个数组结构的有界队列,按照FIFO即先进先出的方式处理任务,但是不保证线程公平的访问队列。
?? public static void main(String[] args) throws InterruptedException {
??? ??? //ArrayBlockingQueue 有界队列,当队列满时,拒绝任务,阻塞等待,直到有任务被移除
??? ??? BlockingQueue<String>? queue = new ArrayBlockingQueue<String>(10);
??? ??? for(int i=0;i<15;i++){
??? ??? ??? queue.put(String.valueOf(i));
??? ??? ??? System.out.println("往队列里面加入数据:" + i);
??? ??? ??? if(i >= 8 ){
??? ??? ??? ??? System.out.println("从队首移除数据:" + queue.take());
??? ??? ??? }
??? ??? }
??? ??? System.out.println("运行结束!");
??? }
运行结果如下:
往队列里面加入数据:0
往队列里面加入数据:1
往队列里面加入数据:2
往队列里面加入数据:3
往队列里面加入数据:4
往队列里面加入数据:5
往队列里面加入数据:6
往队列里面加入数据:7
往队列里面加入数据:8
从队首移除数据:0
往队列里面加入数据:9
从队首移除数据:1
往队列里面加入数据:10
从队首移除数据:2
往队列里面加入数据:11
从队首移除数据:3
往队列里面加入数据:12
从队首移除数据:4
往队列里面加入数据:13
从队首移除数据:5
往队列里面加入数据:14
从队首移除数据:6
运行结束!
4.2:LinkedBlockingQueue
? LinkedBlockingQueue是一个基于链表的有界队列,和ArrayBlockingQueue差不多,也是按照FIFO的原则。LinkedBlockingQueue可以指定容量,也可以不指定,不指定的话,默认最大是Integer.MAX_VALUE。
4.3 PriorityBlockingQueue
?????? 一个支持优先级的无界队列,默认情况下,元素采用自然顺序排序。
4.4 SynchronousQueue
????? 这是一个不存储元素的队列,当某一线程在put时,必须等待其他线程take队列里的数据,否则一直等待。默认情况下访问队列的方式是非公平的,也可以显示的指定为true,即公平的访问队列,按照先进先出的方式访问。

JDK线程池详解

原文:http://314317681.iteye.com/blog/2287422

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!