ThreadPoolExecutor 的简单介绍

为何要用线程池

1. 减小建立和销毁线程的次数
2. 防止并发访问抢占资源, 形成线程阻塞
3. 对线程作一些管理

线程池 ThreadPoolExecutor

总共有四个构造函数,这里只贴出一个,由于其余三个构造函数仍是调用这个构造函数缓存

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    if (corePoolSize < 0 ||
        maximumPoolSize <= 0 ||
        maximumPoolSize < corePoolSize ||
        keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.acc = System.getSecurityManager() == null ?
            null :
            AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

构造函数的参数(或者能够说建立一个线程池须要的条件)并发

1. corePoolSize(线程池基本大小)必须大于或等于0;
2. maximumPoolSize(线程池最大大小)必须大于或等于1;
3. maximumPoolSize必须大于或等于corePoolSize;
4. keepAliveTime(线程存活保持时间)必须大于或等于0;
5. workQueue(任务队列)不能为空;
6. threadFactory(线程工厂)不能为空,默认为DefaultThreadFactory类
7. handler(线程饱和策略)不能为空,默认为ThreadPoolExecutor.AbortPolicy。

四种不一样类型的线程池

1.newCachedThreadPool函数

建立一个可缓存的无界线程池,该方法无参数。当线程池中的线程空闲时间超过60s则会自动回收该线程,当任务超过线程池的线程数则建立新线程。线程池的大小上限为Integer.MAX_VALUE,可看作是无限大。this

2.newFixedThreadPool线程

建立一个固定大小的线程池,该方法可指定线程池的固定大小,对于超出的线程会在LinkedBlockingQueue队列中等待。code

3.newSingleThreadPoolblog

建立一个只有线程的线程池,该方法无参数,全部任务都保存队列LinkedBlockingQueue中,等待惟一的单线程来执行任务,并保证全部任务按照指定顺序(FIFO或优先级)执行。队列

4.newScheduledThreadPool资源

建立一个可定时执行或周期执行任务的线程池,该方法可指定线程池的核心线程个数。rem


向线程池中添加任务

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();
        // 这里作了一个 double check
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    // 若是阻塞队列已满,
        // 线程池中的线程数量小于最大线程数,则建立新的线程
        // 若是线程池中的数量等于最大线程数,调用拒绝服务
    else if (!addWorker(command, false))
        reject(command);
}

execute 方法的执行流程图

execute方法的执行过程

相关文章
相关标签/搜索