首页 > 编程语言 > 详细

java线程池

时间:2019-09-25 16:37:06      阅读:90      评论:0      收藏:0      [点我收藏+]

1.线程池的核心概念

  线程池ThreadPoolExecutor的构造函数有多个参数,但是最重要的参数是workQueue阻塞队列这个参数。线程池正是使用了阻塞队列的特性,使得线程能够一直留在池中,而不会因为run方法执行完成而销毁。线程池的线程会从阻塞队列中取出任务执行,当阻塞队列为空时,阻塞队列会阻塞当前线程(挂起),直到有新的任务进入队列才会被唤醒。所以当目前没有任务时,线程池的线程会被挂起(不消耗cpu),线程就可以一直存在于进程中(只不过被挂起了而已)或者说存在于线程池中。这种方式体现了‘池’的概念,这些线程可以重复使用,有任务时被唤醒执行,没有任务则挂起,减少线程创建和销毁的性能消耗。
技术分享图片
技术分享图片
  1. corePoolSize:核心线程数,不要被这个参数的名称迷惑,其实这个参数实际上是线程池线程数。当线程池实际线程数量小于corePoolSize时,线程池将会创建新线程并加入到线程池中;大于corePoolSize时,会将任务加入队列,而不会继续创建线程,只有队列已经满的情况下,并且当前线程数小于maxPoolSize,才会创建新线程来执行任务。但是这部分线程会在keepAliveTime之后被销毁。
  2. maxPoolSize:最大线程数
  3. keepAliveTime:线程存活时间(在corePore<当前线程数<maxPoolSize情况下有用)
  4. timeUnit:存活时间的时间单位
  5. workQueue:阻塞队列(用来保存等待被执行的任务,关于workQueue参数的取值,JDK提供了4种阻塞队列类型供选择:)
    1. ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO排序任务;
    2. InkedBlockingQuene:基于链表结构的阻塞队列,按FIFO排序任务
    3. SynchronousQuene:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于ArrayBlockingQuene;
    4. PriorityBlockingQuene:具有优先级的无界阻塞队列;
  1. threadFactory:线程工厂,主要用来创建线程;
  2. handler:表示当拒绝处理任务时的策略,有以下四种取值
    1. ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
    2. ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
    3. ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
    4. ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 5.当然也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,如记录日志或持久化存储不能处理的任务。
技术分享图片
 
技术分享图片

2.例子

public class ThreadPool {
public static void main(String[] args) {
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(5,10,2, TimeUnit.SECONDS,new ArrayBlockingQueue<>(5));
 
for (int i=0;i<15;i++){
poolExecutor.execute(new Task(i));
System.out.println("线程池中线程数目:"+poolExecutor.getPoolSize()+",队列中等待执行的任务数目:"+
poolExecutor.getQueue().size()+",已执行完成的任务数目:"+poolExecutor.getCompletedTaskCount());
}
for(;;) {
try {
//if (taskNum < 10) {
Thread.currentThread().sleep(3000);
//}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程池中线程数目:" + poolExecutor.getPoolSize() + ",队列中等待执行的任务数目:" +
poolExecutor.getQueue().size() + ",已执行完成的任务数目:" + poolExecutor.getCompletedTaskCount());
}
//poolExecutor.shutdown();
}
}
class Task implements Runnable {
private int taskNum;
 
public Task(int taskNum){
this.taskNum = taskNum;
}
 
 
@Override
public void run() {
System.out.println("正在执行task "+taskNum);
try {
//if (taskNum < 10) {
Thread.currentThread().sleep(4000);
//}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task "+taskNum+"执行完毕");
}
}
输出:
正在执行task 0 线程池中线程数目:1,队列中等待执行的任务数目:0,已执行完成的任务数目:0 正在执行task 1 线程池中线程数目:2,队列中等待执行的任务数目:0,已执行完成的任务数目:0 线程池中线程数目:3,队列中等待执行的任务数目:0,已执行完成的任务数目:0 正在执行task 2 线程池中线程数目:4,队列中等待执行的任务数目:0,已执行完成的任务数目:0 正在执行task 3 线程池中线程数目:5,队列中等待执行的任务数目:0,已执行完成的任务数目:0 正在执行task 4 线程池中线程数目:5,队列中等待执行的任务数目:1,已执行完成的任务数目:0 线程池中线程数目:5,队列中等待执行的任务数目:2,已执行完成的任务数目:0 线程池中线程数目:5,队列中等待执行的任务数目:3,已执行完成的任务数目:0 线程池中线程数目:5,队列中等待执行的任务数目:4,已执行完成的任务数目:0 线程池中线程数目:5,队列中等待执行的任务数目:5,已执行完成的任务数目:0 线程池中线程数目:6,队列中等待执行的任务数目:5,已执行完成的任务数目:0 正在执行task 10 线程池中线程数目:7,队列中等待执行的任务数目:5,已执行完成的任务数目:0 正在执行task 11 线程池中线程数目:8,队列中等待执行的任务数目:5,已执行完成的任务数目:0 正在执行task 12 线程池中线程数目:9,队列中等待执行的任务数目:5,已执行完成的任务数目:0 正在执行task 13 线程池中线程数目:10,队列中等待执行的任务数目:5,已执行完成的任务数目:0 正在执行task 14 线程池中线程数目:10,队列中等待执行的任务数目:5,已执行完成的任务数目:0 task 1执行完毕 task 3执行完毕 task 11执行完毕 task 10执行完毕 task 4执行完毕 task 2执行完毕 task 0执行完毕 task 14执行完毕 task 12执行完毕 task 13执行完毕 正在执行task 9 正在执行task 8 正在执行task 7 正在执行task 6 正在执行task 5 线程池中线程数目:5,队列中等待执行的任务数目:0,已执行完成的任务数目:10 task 9执行完毕 task 6执行完毕 task 7执行完毕 task 8执行完毕 task 5执行完毕 线程池中线程数目:5,队列中等待执行的任务数目:0,已执行完成的任务数目:15 线程池中线程数目:5,队列中等待执行的任务数目:0,已执行完成的任务数目:15
可以看到线程池线程的数量会维持coreSize的数量,大于core和小于max的线程会被回收。

java线程池

原文:https://www.cnblogs.com/lanqi/p/11585159.html

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