JAVA 线程池ThreadPoolExecutor及核心参数

ThreadPoolExecutor线程池

使用普通线程会带来一些问题,如匿名Runnable无法进行管理,多次执行需要new多次对象;而使用线程池,不仅可以控制并发数、还可以重复利用存在的线程,减少系统的开销。

构造函数:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {}

代码示例:

public static void main(String[] args) {
        //创建核心线程为3/最大线程为5的/空闲时间0/单位秒/阻塞队列容量1/丢弃任务
        ThreadPoolExecutor threadPoolExecutor = 
            new ThreadPoolExecutor(3, 5, 0, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(1),
                 new ThreadPoolExecutor.DiscardPolicy());
        threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {}
            });
        threadPoolExecutor.shutdown(); //关闭线程池
}

核心参数

corePoolSize:核心线程数。即线程池中长时间稳定存活的线程数;

maxPoolSize:最大线程数。即线程池中最大可包含的线程数;

keepAliveTime:空闲线程存活时间。即非核心线程的存活时间;

TimeUnit:时间单位。即TimeUnit.SECONDS秒、MILLISECONDS毫秒、微秒MICROSECONDS和毫微秒NANOSECONDS;

workQueue 任务阻塞队列

有界队列:ArrayBlockingQueue,按 FIFO(先进先出)原则对元素进行排序。

无界队列:LinkedBlockingQueue,容量Integer.MAX_VALUE,无限添加任务直致OOM

直接交换:SynchronousQueue,不存储元素。需等线程调用移除操作,否则处于阻塞状态。

PriorityBlockingQueue:一个具有优先级的无限阻塞队列。

RejectedExecutionHandler 拒绝策略

线程池和阻塞队列都满了时,所采取一种策略处理提交的新任务。

AbortPolicy:(默认策略)丢弃任务,并抛出RejectedExecutionException异常。 

DiscardPolicy:丢弃任务,但是不抛出异常。

DiscardOldestPolicy:丢弃队列最近的任务,并执行当前任务。

CallerRunsPolicy:由提交任务的线程处理该任务。


Executors 静态工厂 

Executors类里有四个线程池创建的静态工厂方法。它是Spring框架提供的线程池技术。底层是基于JDK的ThreadPoolExecutor实现。

分别为:FixedThread、CachedThread、ScheduledThread、SingleThread。

FixedThreadPool 固定大小

初始化指定线程数的线程池,核心线程与最大并发数相同,当线程池没有可执行任务时,也不会释放空闲线程,无界队列。

Executors.newFixedThreadPool(10); 
//底层实现
new ThreadPoolExecutor(10, 10, 0L
                    ,TimeUnit.MILLISECONDS
                    ,new LinkedBlockingQueue<Runnable>());
CachedThreadPool 可缓存

初始化可缓存线程的线程池,默认空闲线程缓存60s,核心线程数是0,最大并发线程为Integer.MAX_VALUE,即2147483647,内部使用SynchronousQueue作为阻塞队列;

Executors.newCachedThreadPool();
//底层实现
new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L
            , TimeUnit.SECONDS
            ,new SynchronousQueue<Runnable>());

线程池的最大值了Integer.MAX_VALUE会导致无限创建线程,注意控制并发的任务数,如果短时创建大量线程,会导致严重的性能问题。线程创建及任务对象会占用堆外内存,它就会使堆外内存和堆内内存其中的一个先耗尽,导致OOM。

ScheduledThreadPool 定时任务

初始化指定的时间周期性的执行任务,核心线程数是1,最大并发线程为Integer.MAX_VALUE,缓存为0。new DelayedWorkQueue()这个类是内部类,为了解它的实现本质在这里直接写。

Executors.newScheduledThreadPool(5);
//底层实现
new ThreadPoolExecutor(1, Integer.MAX_VALUE, 0, 
            NANOSECONDS,
            new DelayedWorkQueue());  
SingleThread 单线程

初始化只有一个线程的线程池。核心线程与并发数都是1个,缓存为0。无界阻塞队列。

Executors.newSingleThreadExecutor()
//底层实现
new FinalizableDelegatedExecutorService(
      new ThreadPoolExecutor(1, 1,0L, 
      TimeUnit.MILLISECONDS,
      new LinkedBlockingQueue<Runnable>())
);

特性:该线程异常结束,会重新创建一个新的线程继续执行任务。


任务Worker

线程池中的任务都被封装成了Worker对象。

Worker类 继承了AQS 类实现了加锁机制

Worker类 实现了Runnable接口,表示是一个线程。

private final class Worker extends AbstractQueuedSynchronizer implements Runnable{
   final Thread thread;
   Runnable firstTask;
   volatile long completedTasks
   Worker(Runnable firstTask) { 
         setState(-1);//设置ASQ的state为-1,设置worker处于不可加锁的状态,为0时允许加锁
         this.firstTask = firstTask;  
         this.thread = getThreadFactory().newThread(this); 
   }
}

任务队列 Workes

添加任务时会存放到一个HashSet的workers队列中。保证worker对象的唯一性。

//HashSet 排列无序,且值不可重复。
private final HashSet<Worker> workers = new HashSet<Worker>();

线程池五个状态

running < shutdown < stop < tidying < terminated

当线程池中的执行数量 >= 核心线程数时,为RUNNING状态。表示此情况下才允许将新任务添加任务队列中。

其它状态都不会接收新任务,不会执行任务队列中的任务;


线程池运行机制 

提交任务 execute 

  1. 当线程池执行数量< core ,新建一个线程执行任务;
  2. 当线程池执行数量 >= core && < maxPool,则创建一个新的线程,放入任务队列;
  3. 当线程池执行数量 > core && 存活时间超过keepalive时,则销毁线程;
  4. 当workers队列数量 >= maxPool && 没有空闲的线程,则拒绝新任务;

添加线程 addWorker

  1. 先判断线程池是否为RUNNING状态,再判断线程池有没有达到最大线程数限制;
  2. 创建work对象添加到works任务队列中等待并更新largestPoolSize池子数量;
  3. 最后启动线程:判断work对象中firstTask不为null,则执行第一个任务;依次循环。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾阳Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值