线程池之ThreadPoolExecutor

所属包:

java.util.concurrent.ThreadPoolExecutor

类关系:

public class ThreadPoolExecutor extends AbstractExecutorService

1. 继承关系

ThreadPoolExecutor 继承了一个抽象类:AbstractExecutorService

public abstract class AbstractExecutorService implements ExecutorService

而这个AbstractExecutorService实现了一个接口:ExecutorService

public interface ExecutorService extends Executor

这个ExecutorService接口又继承了一个类:Executor

public interface Executor

可以看出:

Executor是一个顶层接口,它的子接口ExecutorService继承了它(其实还有一个子接口: ScheduledExecutorService),抽象类AbstractExecutorService实现了这个子接口ExecutorService,最终ThreadPoolExecutor 继承了抽象类AbstractExecutorService并且同时实现了子接口ExecutorService。

2. 构造方法

最简单的一个构造方法:

    /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default thread factory and rejected execution handler.
     * It may be more convenient to use one of the {@link Executors} factory
     * methods instead of this general purpose constructor.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

有五个参数:

corePoolSize - 即使空闲时仍保留在池中的线程数,除非设置 allowCoreThreadTimeOut
maximumPoolSize - 池中允许的最大线程数
keepAliveTime - 当线程数大于核心时,这是多余的空闲线程在终止之前等待新任务的最大时间。
unit - keepAliveTime参数的时间单位
workQueue - 在执行任务之前用于保存任务的队列。 该队列将仅保存execute方法提交的Runnable任务

实际上它调用了同类的另外一个“全能”构造方法,通过 this() 的形式,最后两个参数用的默认值

另外一个构造方法:

    /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    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.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

参数:

corePoolSize - 即使空闲时仍保留在池中的线程数,除非设置 allowCoreThreadTimeOut
maximumPoolSize - 池中允许的最大线程数
keepAliveTime - 当线程数大于内核时,这是多余的空闲线程在终止前等待新任务的最大时间。
unit - keepAliveTime参数的时间单位
workQueue - 用于在执行任务之前使用的队列。 这个队列将仅保存execute方法提交的Runnable任务。
threadFactory - 执行程序创建新线程时使用的工厂
handler - 执行被阻止时使用的处理程序,因为达到线程限制和队列容量 

3. 如何使用

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MyThreadPoolExecutor {

    /**
     * 使用有界队列:
     *  1、当线程数小于corePoolSize时,创建线程执行任务。
     *  2、当线程数大于等于corePoolSize并且workQueue没有满时,放入workQueue中
     *  3、线程数大于等于corePoolSize并且当workQueue满时,新任务新建线程运行,线程总数要小于maximumPoolSize
     *  4、当线程总数等于maximumPoolSize并且workQueue满了的时候执行handler的rejectedExecution。也就是拒绝策略。
     *
     * ThreadPoolExecutor默认有四个拒绝策略:
     *  1、ThreadPoolExecutor.AbortPolicy()           直接抛出异常RejectedExecutionException
     *  2、ThreadPoolExecutor.CallerRunsPolicy()        直接调用run方法并且阻塞执行
     *  3、ThreadPoolExecutor.DiscardPolicy()           直接丢弃后来的任务
     *  4、ThreadPoolExecutor.DiscardOldestPolicy()    丢弃在队列中队首的任务
     *
     *
     *
     */

    public static void main(String[] args) {

        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                1,
                2,
                0L,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(3));

        Runnable[] runs = new Runnable[6];
        for (int i = 0; i < runs.length; i++) {
            runs[i] = new MyTask(i);
        }

        pool.execute(runs[0]);    //线程1个,队列0个
        pool.execute(runs[1]);    //线程1个,队列1个
        pool.execute(runs[2]);    //线程1个,队列2个
        pool.execute(runs[3]);    //线程1个,队列3个
        pool.execute(runs[4]);    //线程2个,队列3个
        pool.execute(runs[5]);    //线程2个,队列3个,拒绝第六个

        pool.shutdown();

    }
}

线程:

public class MyTask implements Runnable {

    private int id;

    public MyTask(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Task-" + id);
    }

}

这个就是最简单的一个使用方法了。ps:最后那个(线程1个,队列0个....)指的是,你仅仅执行runs[0];runs[0]+runs[1];runs[0]+runs[1]+runs[2];....的时候,任务被放到哪里。

但是推荐使用这种方式创建线程池:

package cn.ying.thread.pool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyTest {

    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(5);

        for (int i = 0; i < 10; i++) {
            pool.execute(new MyTask(i));
        }
        pool.shutdown();
    }

    public void note(){
        Executors.newCachedThreadPool();    //无界线程池,可以进行自动线程回收
//        public static ExecutorService newCachedThreadPool() {
//            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
//                                          60L, TimeUnit.SECONDS,
//                                          new SynchronousQueue<Runnable>());//SynchronousQueue:长度为1的队列
//        }
        Executors.newFixedThreadPool(10);    //创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
//        public static ExecutorService newFixedThreadPool(int nThreads) {
//            return new ThreadPoolExecutor(nThreads, nThreads,
//                                          0L, TimeUnit.MILLISECONDS,
//                                          new LinkedBlockingQueue<Runnable>());
//        }
        Executors.newScheduledThreadPool(10);    //创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行
//        public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
//            return new ScheduledThreadPoolExecutor(corePoolSize);
//        }
//        public ScheduledThreadPoolExecutor(int corePoolSize) {
//            super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
//                  new DelayedWorkQueue());
//        }
        Executors.newSingleThreadExecutor();    //创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程
//        public static ExecutorService newSingleThreadExecutor() {
//            return new FinalizableDelegatedExecutorService
//                (new ThreadPoolExecutor(1, 1,
//                                        0L, TimeUnit.MILLISECONDS,
//                                        new LinkedBlockingQueue<Runnable>()));
//        }

    }
}

main方法里面就是相关代码,而note方法则是简单介绍几种方法,注释部分是源码。

就先写这么多吧,以后再补充

时间: 2024-12-24 06:42:49

线程池之ThreadPoolExecutor的相关文章

线程池.(Executors,ThreadPoolExecutor,BlockingQueue,RejectedExecutionHandler).介绍

线程池 Android里面,耗时的网络操作,都会开子线程,在程序里面直接开过多的线程会消耗过多的资源,在众多的开源框架中也总能看到线程池的踪影,所以线程池是必须要会把握的一个知识点; 线程运行机制 开启线程过多,会消耗cpu资源 单核cpu,同一时刻只能处理一个线程,多核cpu同一时刻可以处理多个线程 操作系统为每个运行线程安排一定的CPU时间----时间片,系统通过一种循环的方式为线程提供时间片,线程在自己的时间内运行,因为时间相当短,多个线程频繁地发生切换,因此给用户的感觉就是好像多个线程同

Java并发编程:Java线程池核心ThreadPoolExecutor的使用和原理分析

目录 引出线程池 Executor框架 ThreadPoolExecutor详解 构造函数 重要的变量 线程池执行流程 任务队列workQueue 任务拒绝策略 线程池的关闭 ThreadPoolExecutor创建线程池实例 参考: 引出线程池 线程是并发编程的基础,前面的文章里,我们的实例基本都是基于线程开发作为实例,并且都是使用的时候就创建一个线程.这种方式比较简单,但是存在一个问题,那就是线程的数量问题. 假设有一个系统比较复杂,需要的线程数很多,如果都是采用这种方式来创建线程的话,那么

线程池 一 ThreadPoolExecutor

java.util.concurrent public class ThreadPoolExecutor extends AbstractExecutorService ThreadPoolExecutor实现类 三种ThreadPoolExecutor实现类: ExecutorService?newCachedThreadPool(): 无界线程池,如果有可用线程,当线程池调用execute, 将重用之前的构造函数. 如果没有现有的线程可用,那么就创建新的线程并添加到池中. 核心线程数为0,最

线程池之 ThreadPoolExecutor

线程池之 ThreadPoolExecutor + 面试题 线程池介绍 线程池(Thread Pool):把一个或多个线程通过统一的方式进行调度和重复使用的技术,避免了因为线程过多而带来使用上的开销. 为什么要使用线程池? 可重复使用已有线程,避免对象创建.消亡和过度切换的性能开销. 避免创建大量同类线程所导致的资源过度竞争和内存溢出的问题. 支持更多功能,比如延迟任务线程池(newScheduledThreadPool)和缓存线程池(newCachedThreadPool)等. 线程池使用 创

高并发之——不得不说的线程池与ThreadPoolExecutor类浅析

一.抛砖引玉 既然Java中支持以多线程的方式来执行相应的任务,但为什么在JDK1.5中又提供了线程池技术呢?这个问题大家自行脑补,多动脑,肯定没坏处,哈哈哈... 说起Java中的线程池技术,在很多框架和异步处理中间件中都有涉及,而且性能经受起了长久的考验.可以这样说,Java的线程池技术是Java最核心的技术之一,在Java的高并发领域中,Java的线程池技术是一个永远绕不开的话题.既然Java的线程池技术这么重要(怎么能说是这么重要呢?那是相当的重要,那家伙老重要了,哈哈哈),那么,本文我

线程池:ThreadPoolExecutor

[ThreadPoolExecutor的使用和思考] public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)     1. 参数解释corePoolSize:

Android线程池(二)——ThreadPoolExecutor及其拒绝策略RejectedExecutionHandler使用演示样例

MainActivity例如以下: package cc.vv; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import android.os.Bundle; import android.app.Activity; /** * Demo描写叙述: * 线程池(Threa

Java线程池之ThreadPoolExecutor

前言 线程池可以提高程序的并发性能(当然是合适的情况下),因为对于没有线程的情况下,我们每一次提交任务都新建一个线程,这种方法存在不少缺陷: 1.  线程的创建和销毁的开销非常高,线程的创建需要时间,会延迟任务的执行,会消耗大量的系统资源. 2.  活跃的线程会消耗系统资源,而大量的空闲线程会占用许多内存,给垃圾回收器带来很大的压力,而大量线程在竞争CPU资源的时间还会产生气体的性能开销. 3.  系统在可创建的线程上存在一个限制,如果超过了这个限制,很可能抛出OOM. 我们不难发现,在一定范围

Android线程池(二)——ThreadPoolExecutor及其拒绝策略RejectedExecutionHandler使用示例

MainActivity如下: package cc.vv; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 线程池(ThreadPoo