线程池探索之基础篇

线程池探索之基础篇

一、使用线程池的好处:

    
1)重用线程,避免系统频繁地创建和销毁线程

    
2)任务过多时,通过排队避免创建过多线程,减少系统资源的消耗

阿里开发手册中规定:线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。

二、线程池的内部实现:

JDK中线程池的实现类是ThreadPoolExecutor,先来看看其最重要的构造方法:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) 
参数描述
corePoolSize核心线程数
maximumPoolSize最大线程数
keepAliveTime线程池中线程的数量超过corePoolSize时,多余的空闲线程的存活时间
unitkeepAliveTime的单位
workQueue任务队列
threadFactory线程工厂
handler拒绝策略

ThreadPoolExecutor类核心方法execute如下:

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
        
    int c = ctl.get();
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    else if (!addWorker(command, false))
        reject(command);
}

ThreadPoolExecutor类的任务调度逻辑如下图:
avatar

核心代码为:

三、线程池的工厂类:

    
ThreadPoolExecutor类来自JDK提供的一套Executor框架,框架结构图如下:
avatar

    
Executor框架提供了各种类型的线程池,其内部都是通过ThreadPoolExecutor来实现的,主要有以下工厂方法:

public static ExecutorService newFixedThreadPool(int nThreads)
public static ExecutorService newSingleThreadExecutor()
public static ExecutorService newCachedThreadPool()
public static ScheduledExecutorService newSingleThreadScheduledExecutor()
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

下面来一一描述上述工厂方法:

  • newFixedThreadPool()方法返回一个固定线程数量的线程池。源码如下:
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>());
}
  • newSingleThreadExecutor()方法返回一个只有一个线程的线程池。源码如下:
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}
  • newCachedThreadPool()方法返回一个核心线程数为0,最大线程数为Integer.MAX_VALUE的线程池。源码如下:
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}
  • newSingleThreadScheduledExecutor方法返回一个ScheduledExecutorService,线程池大小为1。ScheduledExecutorService是在ExecutorService的基础上增加了定时执行任务的功能。源码如下:
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
    return new DelegatedScheduledExecutorService
        (new ScheduledThreadPoolExecutor(1));
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE,
          DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
          new DelayedWorkQueue());
}
  • newScheduledThreadPool()方法也返回一个ScheduledExecutorService,但可指定线程池的线程数量。源码如下:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE,
          DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
          new DelayedWorkQueue());
}

阿里开发手册中规定:线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,避免资源耗尽的风险。

Executors返回的线程池对象的弊端如下:

  1. FixedThreadPool和SingleThreadPool:

    
允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。

  1. CachedThreadPool和ScheduledThreadPool:

    
允许创建的线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值