线程池基础篇

一、什么是线程池?为什么要用线程池?

1、 降低资源的消耗。降低线程创建和销毁的资源消耗;

2、 提高响应速度:线程的创建时间为T1,执行时间T2,销毁时间T3,免去T1和T3的时间

3、 提高线程的可管理性。

二、线程池的创建

ThreadPoolExecutor,jdk所有线程池实现的父类

三、参数介绍

先看构造函数:

/**
     * 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.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;
    }

再看看参数的具体解释:

// 阻塞队列
private final BlockingQueue<Runnable> workQueue;

// 互斥锁
private final ReentrantLock mainLock = new ReentrantLock();

// 线程集合。一个Worker对应一个线程。
private final HashSet<Worker> workers = new HashSet<Worker>();

// “终止条件”,与“mainLock”绑定。
private final Condition termination = mainLock.newCondition();

// 线程池中线程数量曾经达到过的最大值。
private int largestPoolSize;

// 已完成任务数量
private long completedTaskCount;

// ThreadFactory对象,用于创建线程。
private volatile ThreadFactory threadFactory;

// 拒绝策略的处理句柄。
private volatile RejectedExecutionHandler handler;

// 保持线程存活时间。
private volatile long keepAliveTime;

private volatile boolean allowCoreThreadTimeOut;

// 核心池大小
private volatile int corePoolSize;

// 最大池大小
private volatile int maximumPoolSize;

参数详解:

1.核心线程  int  corePoolSize:核心池大小

the number of threads to keep in the pool, even if they are idle, unless {@code allowCoreThreadTimeOut} is set

线程池在new 出来后是没有线程的,仅当执行任务的时候才会创建线程;

当然也可以调用线程池的prestartAllCoreThreads()方法,让线程池在创建时就创建corePoolSize数目的线程;

核心线程在任务完成时,会new 新的线程,并且不会销毁,除非设置allowCoreThreadTimeOut

public void allowCoreThreadTimeOut(boolean value) {
        if (value && keepAliveTime <= 0)
            throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
        if (value != allowCoreThreadTimeOut) {
            allowCoreThreadTimeOut = value;
            if (value)
                interruptIdleWorkers();
        }
    }

2 最大线程数 int  maximuxPoolSize:最大线程池大小

the maximum number of threads to allow in the pool 线程池所允许创建的最大线程数;

3 存活时间 long  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.

当线程池中的线程数量大于核心池大小后,超过核心数量的线程在keepAliveTime的时间内可以等待一个新任务,超过时间就会销毁;

4. TimeUnit  timeUnit:keepAliveTime的单位,

TimeUnit  枚举值有:DAYS、HOURS、MINUTES、SECONDS、MILLISECONDS(毫秒)、MICROSECONDS(微秒)、NANOSECONDS(纳秒);

5.工作队列 BlockingQueue  workQueue:阻塞任务队列

  执行前的任务,存储在队列中(线程池会先使用核心线程,当核心线程用完才会使用队列);

  线程池只会execute Runnable任务,Callable任务也会包装成Runnable任务

  主要实现类有:

  1)LinkedBlockingQueue:基于链表的无界(默认构造函数为:最大值Integer.MAX_VALUE容量)阻塞队列,按FIFO(先进先出)的规则存取任务

  2)ArrayBlockingQueue:基于数组的有界阻塞队列,按FIFO的规则对任务进行存取,必须传入参数来定义队列大小

  3)DelayedWorkQueue:基于堆的延迟队列,Executors.newScheduledThreadPool(...)中使用了该队列

  4)PriorityBlockingQueue:具有优先级的阻塞队列

  5)SynchronousQueue:不存储任务的阻塞队列,每一个存入对应一个取出,串行化队列

  吞吐量:SynchronousQueue > LinkedBlockingQueue > ArrayBlockingQueue

6 线程创建工厂 ThreadFactory  threadFactory:线程工厂

用来创建线程,可以通过自定义线程工厂给新创建的线程设置更合理的名字、设置优先级和是否守护线程。可以根据需要自定义线程工厂。

static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            //线程组
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            //名称前缀,这就是我们打印的线程池中线程名称前缀
            //可以修改的,如果自定义线程工厂
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        //工厂创建线程
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                //非守护线程
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                //常规优先级
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

7 拒绝策略 RejectedExecutionHandler  handler:拒绝任务的接口处理器

达到队列和线程池的最大线程数限制,就执行拒绝策略

拒绝策略有:

  1)AbortPolicy:拒绝任务并抛出异常,默认的策略

  2)DiscardPolicy:直接拒绝不抛出异常

  3)DiscardOldestPolicy:丢弃队列中最远的一个任务(最先进入队列的,FIFO),并执行当前任务;

  4)CallerRunsPolicy:只用调用者所在的线程来执行任务,不管其他线程的事。

四、我们看线程池的主要方法

1.execute()方法

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn‘t, by returning false.
         *
         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         *
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         */
        //AtomicInteger存
        int c = ctl.get();
        //工作线程小于corePoolSize
        if (workerCountOf(c) < corePoolSize) {
            //添加一个core线程,此处参数为true,表示添加的线程是core容量下的线程
            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);
            //线程池在运行,有效线程数为0
            else if (workerCountOf(recheck) == 0)
                //添加一个空线程进线程池,使用非core容量线程
                //仅有一种情况,会走这步,core线程数为0,max线程数>0,队列容量>0
                //创建一个非core容量的线程,线程池会将队列的command执行
                addWorker(null, false);
        }
        //线程池停止了或者队列已满,添加maximumPoolSize容量工作线程,如果失败,执行拒绝策略
        else if (!addWorker(command, false))
            reject(command);
    }

    final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }

看上面的英文注释,有3步:

1) 检查core线程池数量<corePoolSize数量,是,可以提交任务或新建线程执行任务 。

2)如果corePoolSize线程数量已使用,如果队列容量未满,则加入队列。

3)队列已满,创建maximumPoolSize线程数量执行;如果失败则执行关闭线程池或者拒绝策略。

继续跟踪 private boolean addWorker(Runnable firstTask, boolean core)

rivate final ReentrantLock mainLock = new ReentrantLock();

    private final HashSet<Worker> workers = new HashSet<Worker>(); 

   /**
     * Checks if a new worker can be added with respect to current
     * pool state and the given bound (either core or maximum). If so,
     * the worker count is adjusted accordingly, and, if possible, a
     * new worker is created and started, running firstTask as its
     * first task. This method returns false if the pool is stopped or
     * eligible to shut down. It also returns false if the thread
     * factory fails to create a thread when asked.  If the thread
     * creation fails, either due to the thread factory returning
     * null, or due to an exception (typically OutOfMemoryError in
     * Thread.start()), we roll back cleanly.
     *
     * @param firstTask the task the new thread should run first (or
     * null if none). Workers are created with an initial first task
     * (in method execute()) to bypass queuing when there are fewer
     * than corePoolSize threads (in which case we always start one),
     * or when the queue is full (in which case we must bypass queue).
     * Initially idle threads are usually created via
     * prestartCoreThread or to replace other dying workers.
     *
     * @param core if true use corePoolSize as bound, else
     * maximumPoolSize. (A boolean indicator is used here rather than a
     * value to ensure reads of fresh values after checking other pool
     * state).
     * @return true if successful
     */
    private boolean addWorker(Runnable firstTask, boolean core) {
        //自旋检查
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            //如果线程池已关闭;线程池正在关闭,提交的任务为null,任务队列不为空,则直接返回失败
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                int wc = workerCountOf(c);
                //工作线程数达到或超过最大容量,或者添加core线程达到最大容量或者添加max线程达到最大容量,直接失败
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                //线程数+1,CAS原子操作,成功后跳出循环
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                //原子操作失败,判断线程池运行状态是否已改变
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            //所有代码的核心,new Worker,创建了线程,或者复用线程
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                //线程池是操作多线程,加锁
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                    int rs = runStateOf(ctl.get());

                    //再检查一次,线程池在运行或正在停止
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        //添加的线程不能是活跃线程
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        //添加线程存储,HashSet存储
                        workers.add(w);
                        //重入锁最大池数量
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    //上面的标记,启动线程
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                //失败处理
                addWorkerFailed(w);
        }
        return workerStarted;
    }

Worker 是啥

private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        /**
         * This class will never be serialized, but we provide a
         * serialVersionUID to suppress a javac warning.
         */
        private static final long serialVersionUID = 6138294804551838833L;

        /** Thread this worker is running in.  Null if factory fails. */
        final Thread thread;
        /** Initial task to run.  Possibly null. */
        Runnable firstTask;
        /** Per-thread task counter */
        volatile long completedTasks;

        /**
         * Creates with given first task and thread from ThreadFactory.
         * @param firstTask the first task (null if none)
         */
        Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            //此处创建了线程,线程工厂,使用this
            this.thread = getThreadFactory().newThread(this);
        }

        /** Delegates main run loop to outer runWorker  */
        public void run() {
            runWorker(this);
        }

Worker实现AQS和Runnable接口 ,是线程接口实现

追踪 run方法

/**
     * Main worker run loop.  Repeatedly gets tasks from queue and
     * executes them, while coping with a number of issues:
     *
     * 1. We may start out with an initial task, in which case we
     * don‘t need to get the first one. Otherwise, as long as pool is
     * running, we get tasks from getTask. If it returns null then the
     * worker exits due to changed pool state or configuration
     * parameters.  Other exits result from exception throws in
     * external code, in which case completedAbruptly holds, which
     * usually leads processWorkerExit to replace this thread.
     *
     * 2. Before running any task, the lock is acquired to prevent
     * other pool interrupts while the task is executing, and then we
     * ensure that unless pool is stopping, this thread does not have
     * its interrupt set.
     *
     * 3. Each task run is preceded by a call to beforeExecute, which
     * might throw an exception, in which case we cause thread to die
     * (breaking loop with completedAbruptly true) without processing
     * the task.
     *
     * 4. Assuming beforeExecute completes normally, we run the task,
     * gathering any of its thrown exceptions to send to afterExecute.
     * We separately handle RuntimeException, Error (both of which the
     * specs guarantee that we trap) and arbitrary Throwables.
     * Because we cannot rethrow Throwables within Runnable.run, we
     * wrap them within Errors on the way out (to the thread‘s
     * UncaughtExceptionHandler).  Any thrown exception also
     * conservatively causes thread to die.
     *
     * 5. After task.run completes, we call afterExecute, which may
     * also throw an exception, which will also cause thread to
     * die. According to JLS Sec 14.20, this exception is the one that
     * will be in effect even if task.run throws.
     *
     * The net effect of the exception mechanics is that afterExecute
     * and the thread‘s UncaughtExceptionHandler have as accurate
     * information as we can provide about any problems encountered by
     * user code.
     *
     * @param w the worker
     */
    final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        //任务线程的锁状态默认为-1(构造函数设置的),此时解锁+1,变为0,是锁打开状态,允许中断。
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
            //如果添加的任务存在或者队列取
            while (task != null || (task = getTask()) != null) {
                w.lock();
                // If pool is stopping, ensure thread is interrupted;
                // if not, ensure thread is not interrupted.  This
                // requires a recheck in second case to deal with
                // shutdownNow race while clearing interrupt

                //线程池正在停止,当前线程未中断
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    //中断当前线程
                    wt.interrupt();
                try {
                    //准备,空方法,可自定义实现
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                        //本质,直接调用run方法
                        task.run();
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                        //结束,空方法,可自定义实现
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    //记录任务数
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            //worker结束处理
            processWorkerExit(w, completedAbruptly);
        }
    }

跟踪 getTask

private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?
        //自旋锁
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            //检查线程池是否关闭,队列为空
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                //减少工作线程数量
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);

            // Are workers subject to culling?
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

            //工作线程数超过core或者max,或者队列为空,工作线程存在
            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                //减少任务数
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {
                //超时机制控制队列取元素
                //take        移除并返回队列头部的元素     如果队列为空,则阻塞
                //poll        移除并返问队列头部的元素    如果队列为空,则返回null
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

跟踪 processWorkerExit(w, completedAbruptly);

/**
     * Performs cleanup and bookkeeping for a dying worker. Called
     * only from worker threads. Unless completedAbruptly is set,
     * assumes that workerCount has already been adjusted to account
     * for exit.  This method removes thread from worker set, and
     * possibly terminates the pool or replaces the worker if either
     * it exited due to user task exception or if fewer than
     * corePoolSize workers are running or queue is non-empty but
     * there are no workers.
     *
     * @param w the worker
     * @param completedAbruptly if the worker died due to user exception
     */
    private void processWorkerExit(Worker w, boolean completedAbruptly) {
        //正常执行,此处设置为法false
        if (completedAbruptly) // If abrupt, then workerCount wasn‘t adjusted
            decrementWorkerCount();

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            //任务数增加
            completedTaskCount += w.completedTasks;
            //移除HashSet的线程
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

        //尝试停止线程池
        tryTerminate();

        int c = ctl.get();
        //如果没有停止线程池
        if (runStateLessThan(c, STOP)) {
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                //core线程数量为0或者队列为空,默认1
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                //工作线程比core线程多,直接返回
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }
            //当前线程运行结束,增加空线程,容量maximumPoolSize
            addWorker(null, false);
        }
    }

addWorker 失败处理

/**
     * Rolls back the worker thread creation.
     * - removes worker from workers, if present
     * - decrements worker count
     * - rechecks for termination, in case the existence of this
     *   worker was holding up termination
     */
    private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (w != null)
                //工作线程移除任务HashSet
                workers.remove(w);
            //工作线程数量-1
            decrementWorkerCount();
            //尝试停止线程池
            tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }

tryTerminate

/**
     * Transitions to TERMINATED state if either (SHUTDOWN and pool
     * and queue empty) or (STOP and pool empty).  If otherwise
     * eligible to terminate but workerCount is nonzero, interrupts an
     * idle worker to ensure that shutdown signals propagate. This
     * method must be called following any action that might make
     * termination possible -- reducing worker count or removing tasks
     * from the queue during shutdown. The method is non-private to
     * allow access from ScheduledThreadPoolExecutor.
     */
    final void tryTerminate() {
        for (;;) {
            int c = ctl.get();
            //线程池在运行或者状态在变化中,或者正在停止但队列有任务,直接返回
            if (isRunning(c) ||
                runStateAtLeast(c, TIDYING) ||
                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;
            //有任务工作线程
            if (workerCountOf(c) != 0) { // Eligible to terminate
                //中断所有线程
                interruptIdleWorkers(ONLY_ONE);
                return;
            }

            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                //线程池状态改变
                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                    try {
                        //结束线程池,空方法,does nothing
                        terminated();
                    } finally {
                        //设置线程池状态,结束
                        ctl.set(ctlOf(TERMINATED, 0));
                        //唤醒所有wait线程
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }

    private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers) {
                Thread t = w.thread;
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * Method invoked when the Executor has terminated.  Default
     * implementation does nothing. Note: To properly nest multiple
     * overridings, subclasses should generally invoke
     * {@code super.terminated} within this method.
     */
    protected void terminated() { }

大量的CAS和自旋锁;位运算算法和重入锁AQS。

看看销毁线程池方法

public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            //检查权限
            checkShutdownAccess();
            //CAS 更新线程池状态
            advanceRunState(SHUTDOWN);
            //中断所有线程
            interruptIdleWorkers();
            //关闭,此处是do nothing
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        //尝试结束,上面代码已分析
        tryTerminate();
    }

2. submit方法

/**
     * @throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc}
     */
    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }

    /**
     * @throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc}
     */
    public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }

    /**
     * @throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc}
     */
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }

执行图解:

五、预定义的线程池

FixedThreadPool

创建固定线程数量的,适用于负载较重的服务器,使用了无界队列

SingleThreadExecutor

创建单个线程,需要顺序保证执行任务,不会有多个线程活动,使用了无界队列

CachedThreadPool

会根据需要来创建新线程的,执行很多短期异步任务的程序,使用了SynchronousQueue

WorkStealingPool(JDK7以后) 

基于ForkJoinPool实现

ScheduledThreadPoolExecutor 

需要定期执行周期任务,Timer不建议使用了。

newSingleThreadScheduledExecutor:只包含一个线程,只需要单个线程执行周期任务,保证顺序的执行各个任务

newScheduledThreadPool 可以包含多个线程的,线程执行周期任务,适度控制后台线程数量的时候

方法说明:

schedule:只执行一次,任务还可以延时执行

scheduleAtFixedRate:提交固定时间间隔的任务

scheduleWithFixedDelay:提交固定延时间隔执行的任务

package com.youyou.test.demo01;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Demo02 {
    static class TestThreadPool implements Runnable{
        @Override
        public void run(){
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        //指定3个长度的工作队列
        LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>(3);
        //指定线程池参数:核心线程数,线程池最大线程数量,活跃时间,工作队列
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(4,7,90,TimeUnit.SECONDS,workQueue);
        for (int i = 0; i < 15; i++) {
            poolExecutor.execute(new Thread(new TestThreadPool(),"线程:".concat(i+"")));
            System.out.println("线程池中活跃线程数"+poolExecutor.getActiveCount());
            if(workQueue.size()>0){
                System.out.println("被阻塞的线程数为:"+workQueue.size());
            }
        }
    }
}

原文地址:https://www.cnblogs.com/lys-lyy/p/11104976.html

时间: 2024-10-04 01:29:53

线程池基础篇的相关文章

Java(Android)线程池---基础篇

1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? 1 newThread(newRunnable(){ 2 3 @Override 4 publicvoidrun(){ 5 // TODO Auto-generated method stub 6 } 7 }).start(); 那你就out太多了,new Thread的弊端如下: a. 每次new Thread新建对象性能差.b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致

Android多线程编程之线程池学习篇(一)

Android多线程编程之线程池学习篇(一) 一.前言 Android应用开发中多线程编程应用比较广泛,而应用比较多的是ThreadPoolExecutor,AsyncTask,IntentService,HandlerThread,AsyncTaskLoader等,为了更详细的分析每一种实现方式,将单独成篇分析.后续篇章中可能涉及到线程池的知识,特此本篇分析为何使用线程池,如何使用线程池以及线程池的使用原理. 二.Thread Pool基础 进程代表一个运行中的程序,一个运行中的Android

c# 多线程线程池基础

线程池的作用        在上一篇中我们了解了创建和销毁线程是一个昂贵的操作,要耗费大量的时间,太多的线程会浪费内存资源,当线程数量操作计算机CPU的数量后操作系统必须调度可运行的线程并执行上下文切换,所有太多的线程还会影响性能,那么有没有办法让线程可以重复使用了,让线程干完活之后不用销毁,把它放在一个容器中, 等待下次有任务的时候在从容器中取出来就行了,这样就避免了创建和销毁所带来的性能损耗,所有线程池的作用总结起来就是:因为创建一个线程的代价较高,因此我们使用线程池设法复用线程. 线程基础

并发包的线程池第二篇--Executors的构造

上一篇讲述了ThreadPoolExecutor的执行过程,我们也能看出来一个很明显的问题:这个线程池的构造函数比较复杂,对于不十分理解其运作原理的程序员,自己构造它可能体现和想象中不一样的行为.比如阻塞队列放什么,corePoolSize怎么设置等等. 所以和Math这种工具类一样,并发包也提供了一种工具类:Executors. 首先这个工具类的作用就是:提供静态方法帮你构造不同的线程池.那么先分析一下它的设计模式: 1,静态工厂方法模式,静态方法帮你构造线程池. 2,外观模式,用一个简单的接

Java:线程池基础

基本认识 以下摘自百度百科 线程池的概念:线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务. 线程池的作用:在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收.所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁.如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些"池化资

delphi 线程池基础 TSimplePool

1. TSimpleThread 2. TSimpleList 3. 以1,2构成 TSimplePool 用法 先定义: TDoSomeThingThread=class(TSimpleThread) ; 并给 TDoSomeThingThread reintroduce Create 不带参数的构造函数. 再定义  TDoSomeThingPool=class(TSimpleTool<TDoSomeThing>); 最后,只需在 TDoSomeThingPool 写线程调度的代码就行了,可

并发编程—7.2线程池基础

目录 1.什么是线程池?为什么要用线程池? 2.实现一个我们自己的线程池 3.JDK中的线程池和工作机制 3.1 线程池的创建 3.2 提交任务 3.3 关闭线程池 3.4 工作机制 4.合理配置线程池 5.预定义的线程池 6.Executor框架 7.了解CompletionService 1.什么是线程池?为什么要用线程池? 降低资源的消耗.线程的创建和销毁 提高响应速度.线程的创建时间为T1,执行时间T2,销毁时间T3,免去T1和T3的时间 提高线程的可管理性. 2.实现一个我们自己的线程

线程池基础

package com.how2java.tmall.train.ThreadPool; import java.util.concurrent.*; import static java.util.concurrent.TimeUnit.NANOSECONDS; /** * @Author: yslu * @Date: 2019-09-30 8:44 * @description: */ public class ThreadPoolExecutorDemo { public static v

Java线程池-基础

线程池的核心类:ThreadPoolExecutor ,类图如下: (I:代表接口,C:代表实现类) I:Executor I:ExecutorService C:AbstractExecutorService C:ThreadPoolExecutor 构造函数: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Run