java多线程篇---常用线程池与线程池的原理(全)

java线程池如何实现

  线程池中的线程,其实就是抽象为静态内部类worker,通过AQS框架实现。这个线程被存放在线程池中的HashSet workers成员变量中。需要执行的任务放在成员变量workerQueue中,所以流程就是从workerQueue中取出任务,放到workers中执行。

创建线程池主要的构造参数

  • corePoolSize:核心线程数。
  • maxinumPoolsize:线程池允许的最大线程数。
  • keepAliveTime:超过核心线程数那部分闲置线程所存活的时间。
  • workQueue:执行任务前保存任务的队列,execute()方法提交的任务。

线程池的创建与工作流程

  线程池默认初始化后不会启动worker,而是有请求后才会启动。每当我们用execute()方法添加一个任务时,线程池工作流程如下:

  • 如果正在运行的线程数量小于corePoolSize,立即创建新的线程来执行这个任务。
  • 如果正在运行的线程数量大于或者等于corePoolSize,那么这个任务将会放到等待队列中。
  • 如果队列满了,而且正在运行的线程数小于maxinumPoolsize,那么会创建出非核心线程来执行任务。
  • 如果队列满了,而且正在运行的线程数大于或者等于maxinumPoolsize,那么任务会被拒绝并抛出RejectExecutionException̶异常。
  • 当一个线程完成任务后,他会从队列中取下一个任务执行。当一个线程空闲,并且超过keepAliveTime时间,线程池就会判断,如果当前线程数大于corePoolSize,那么这个线程就会被停掉,所以所有线程完成任务后,线程数还是核心线程数。

常用线程池

1.SingleThreadExecutor
这个线程只有一个核心线程在执行任务,单线程串行执行所有任务。如果这个线程突然挂掉了,那么会有一个新线程来替代它。任务会按照提交的顺序执行。适用于任务按顺序执行的场景。

  • corePoolSize:1,只有一个线程在工作
  • maxinumPoolsize:1
  • keepAliveTime:0L
  • workQueue:new LinkedBlockingQueue(),无界队列

2.FixedThreadPool
一个固定大小的线程池,只有核心线程在工作。每提交一个任务就会创建新的线程,直到达到maxinumPoolsize。如果有线程异常挂掉,会有新的线程替代它。适用于任务量固定并且耗时的场景。

  • corePoolSize:nThreads
  • maxinumPoolsize:nThreads
  • keepAliveTime:0L
  • workQueue:new LinkedBlockingQueue(),无界队列

3.CachedThreadPool
无界线程池,如果线程池大小超过了执行任务所需要的线程数,那么它就会回收空闲60秒的线程。当任务增加时,它又可以自动的创建新的线程。具体线程池有多大完全取决于jvm。适用于任务量大但耗时少的任务。

  • corePoolSize:0
  • maxinumPoolsize: Integer.MAX_VALUE
  • keepAliveTime:60L
  • workQueue:new SynchronousQueue(),缓冲区为1的阻塞队列

4.ScheduledThreadPool
核心线程固定,大小无限制。支持定时和周期性任务,如果闲置,非核心线程会在DEFAULT_KEEPALIVEMILLIS内回收。适用于定时任务或者周期性任务

  • corePoolSize:corePoolSize
  • maxinumPoolsize: Integer.MAX_VALUE
  • keepAliveTime:DEFAULT_KEEPALIVEMILLIS
  • workQueue:new DelayedWorkQueue(),优先级队列

如何提交线程

1.execute(): ExecutorService.execute(Runable runable);
2. submit(): ExecutorService.submit()返回的是Future对象。可以用isDone()来查询Future是否完成,当任务完成时,可以用get()来获取结果。如果直接用get()的话,方法会阻塞,直到结果完成。

猜你喜欢

转载自blog.csdn.net/qq_39753008/article/details/107655984
今日推荐