Java解析线程池

什么是线程池

线程池就是装有线程的池子,把要执行的线程交给线程池来处理,通过维护一定数量的线程池来达到多个线程的复用。

线程池的好处

如果不用线程池,每个线程都要通过new Thread(xxRunnable).start()的方法来创建并运行一个线程。每次创建一个和销毁一个线程都是要消耗系统资源的。当线程数达到一定数量就会耗尽系统的CPU和内存资源,也会造成GC频繁收集和停顿。而线程复用节省了很大的一部分系统资源,当线程一段时间不再有任务时自动销毁,不会常驻内存。

线程池核心类

public ThreadPoolExecutor(int corePoolSize,//线程池的核心大小,也是最小的线程池大小
                              int maximumPoolSize,//最大线程池大小
                              long keepAliveTime,//空余线程存活时间,指的是超过corePoolSize大小的空余线程多长时间后销毁
                              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,创建新线程执行任务
  2. 如果线程池中的线程大于corePoolSize,把任务存储到工作队列workQueue中等待执行
  3. 如果workQueue也满了,线程数小于maximumPoolSize就创建新线程执行任务;线程数大于等于maximumPoolSize就执行拒绝策略

线程池分类

Executors是JDK提供的创建线程池的工厂类

  • newFixedThreadPool
    固定线程池,核心线程数和最大线程固定相等,空闲存活时间为0,工作队列是最大为Integer.MAX_VALUE大小的阻塞队列。执行任务时,如果线程都很忙,就会等到工作队列有空闲线程时再执行,队列满了就执行默认的拒绝策略。
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
  • newCachedThreadPool
    带缓冲线程池,核心线程数为0,最大线程数为Integer最大值大小,超过0个的空闲线程在60秒后销毁。SynchronousQueue这是一个直接提交的队列,每个新任务都会有线程来执行。如果线程池有可用线程则执行任务,没有就创建一个来执行。线程池中的线程数不确定。一般建议执行速度较快较小的线程,不然这个最大线程池边界过大容易造成内存溢出。
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
  • newSingleThreadExecutor
    单线程线程池,核心线程数和最大线程数均为1,空闲线程存活0毫秒。每次只执行一个线程,多余的先存储到工作队列,一个一个执行,保证了线程的顺序执行。
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
  • newScheduledThreadPool
    调度线程池,即按一定的周期执行任务,即定时任务,对ThreadPoolExecutor进行了包装。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

拒绝策略

  • AbortPolicy
    直接抛出拒绝异常,这也是默认的拒绝策略。
public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }
  • CallerRunsPolicy
    如果线程池未关闭,则会在调用者线程中直接执行新任务,导致主线程提交线程性能变慢。
public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code CallerRunsPolicy}.
         */
        public CallerRunsPolicy() { }

        /**
         * Executes task r in the caller's thread, unless the executor
         * has been shut down, in which case the task is discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }
  • DiscardPolicy
    不处理新任务,丢弃。
public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardPolicy}.
         */
        public DiscardPolicy() { }

        /**
         * Does nothing, which has the effect of discarding task r.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }
  • DiscardOldestPolicy
    抛弃最老的任务执行新任务
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
        public DiscardOldestPolicy() { }

        /**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }

提交线程

ExecutorService es = Executors.newFixedThreadPool(3);//定义一个固定大小的线程池
es.submit(xxRunnble);//提交线程,execute没有返回值,不知道线程结果
es.execute(xxRunnble);//提交线程,submit返回一个Future对象,并能在主线程中通过Future的get方法捕获线程中的异常

关闭线程池

es.shutdown();//不再接受新的任务,等执行完所有任务后关闭线程池。
es.shutdownNow();//不再接受新的任务,尝试停止所有任务后关闭线程池,返回未处理的线程list列表。

欢迎关注我的公众号

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章