Java线程池

Java线程池#

线程池的执行过程#

  1. 当向线程池提交一个新的任务,线程池首先判断核心线程池的线程是否都在执行任务。如果不是,创建一个新的工作线程来执行任务。如果核心线程的线程都在执行任务,则进入下一个流程。

  2. 线程池判断工作队列是否已经满了,如果工作队列没有满,则将新提交的任务存储在这个工作队列里如果工作队列满了,则进入下一个流程

  3. 线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

线程池创建的参数#

public ThreadPoolExecutor(
 int corePoolSize,  
 int maximumPoolSize,
 long keepAliveTime,
 TimeUnit unit,
 BlockingQueue<Runnable> workQueue,
 ThreadFactory threadFactory,
 RejectedExecutionHandler handler
)
  1. corePoolSize(线程池的基本大小,核心线程池大小):提交一个新的任务到线程池,就会创建一个新的线程来执行任务,即使有空闲线程来执行任务,也会创建线程。直到待执行的任务数大于线程池基本大小就不再创建新的线程。如果调用了线程池的prestartCoreThread()方法,线程池会提前创建并启动所有的基本线程。

  2. workQueue(工作队列):用于在执行任务之前保存任务的队列。此队列用于保存向线程池提交的未处理的任务。

    1. ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按FIFO原则对元素进行排序。
    2. LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量通常高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用这个队列。
    3. SynchronousQueue:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态。
    4. DelayedWorkQueue:一个基于延迟时间排序的队列,Executors.newScheduledThreadPool()使用这个队列。
    5. LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列
    6. LinkedTransferQueue:一个由链表结构组成的无界阻塞队列
    7. PriorityBlockingQueue:一个具有优先级的无限阻塞队列
  3. maximumPoolSize(线程池最大数量):线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务,如果使用了无界的任务队列这个参数就没有什么效果。

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

  5. RejectedExecutionHandler(饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。

    1. AbortPolicy(默认策略):直接抛出异常;

    2. CallerRunsPolicy:只用调用者所在线程来运行任务;

    3. DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务

    4. DiscardPolicy:不处理,丢弃掉

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

  7. unit:(线程活动保持时间的单位):可选的单位有天(DAYS)、小时(HOURS)、分钟(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和纳秒(NANOSECONDS,千分之一微秒)。

向线程池提交任务#

  1. 使用execute() 方法提交。实现了Runable接口的线程
  ExecutorService threadPool = Executors.newFixedThreadPool(1);
   threadPool.execute(() -> {
   //TODO
   });
  1. 使用submit()方法提交。用于提交需要返回值的任务。线程池会返回一个future类型的对象
  <T> Future<T> submit(Callable<T> task);
  <T> Future<T> submit(Runnable task, T result);
  Future<?> submit(Runnable task
  ExecutorService threadPool = Executors.newFixedThreadPool(1);
  Future<String> future = threadPool.submit(() -> "Hello");
  try {
       String hello = future.get();
  } catch (InterruptedException e) {
       e.printStackTrace();
  } catch (ExecutionException e) {
       e.printStackTrace();
  }finally {
   // 关闭线程池
      threadPool.shutdown();
  }

注:本文参考于《Java并发编程艺术》第九章 Java中的线程池

作者:pangcode

出处:https://www.cnblogs.com/pangcode/p/16737103.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   老王日记  阅读(78)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu