Java线程池简略分析

1.什么是线程?为什么要用线程池?

    线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务,线程池都是后台线程。

    Java中创建和销毁一个线程是比较昂贵的操作,频繁的创建和销毁线程会影响系统性能。使用线程池可以节省系统的开销,节省创建和销毁线程的时间等。

 

2.线程池的几个对象

  • Executor:Java中的线程池接口,接口中只含有一个void execute(Runnable command)方法,用于执行已提交的线程任务,提供了一种将任务提交和运行的机制,是最顶层接口定义,有多个实现类。
  • ExecutorService:继承了Executor接口,在Executor的基础上加入了线程池生命周期管理,一般使用该接口来实现和管理多线程,并且还支持Callable形式的任务。
    • void shutdown():关闭当前的线程池,并停止线程池内所有的线程,同时不再接受新的线程提交。
    • List shutdownNow():停止所有正在执行的任务,停止等待处理的任务,并返回正在等待处理的任务列表。
    • boolean isShutdown():判断当前线程池是否关闭。
    • boolean isTerminated():如果当前池关闭后所有的任务都完成,则返回true。
    • boolean awaitTermination(long timout, @NotNull TimeUnit unit):阻塞线程池,直到所有的任务在关闭请求后都执行完成,或者超时,或者是当前线程中断,以先发生的情况为准,如果请求都执行完成返回true,如果在终止前超时返回false。
    • Future submit(Callable task):提交一个Callable类型的线程任务,返回Futrue对象用于描述当前任务状态,提交task不能为空,否则会触发NullPointerException异常;如果任务没有预期执行,也会抛出RejectExecutionException异常。
    • Future submit(Runnable task, T result):提交Runable类型的任务,返回Futrue对象用于描述当前任务状态,提交task不能为空,否则会触发NullPointerException异常;如果任务没有预期执行,也会抛出RejectExecutionException异常。如果成功提交任务的话,Futrue对象中code则返回给定的result。
    • Future submit(Runnable task):提交Runable类型的任务,返回Futrue对象用于描述当前任务状态,提交task不能为空,否则会触发NullPointerException异常;如果任务没有预期执行,也会抛出RejectExecutionException异常
    • List> invokeAll(Collection> tasks):提交所有可执行的Callable类型任务,返回Futrue列表,具有阻塞性,需要等所有的线程任务执行完毕,返回全部任务的结果值。
    • List> invokeAll(Collection> tasks,long timeout, TimeUnit unit):提交所有可执行的callable类型任务,设置超时时间,超出最大等待时间,中断剩余未执行的任务,返回当前执行的TimeUnit对象。具有阻塞性,需要等所有的线程任务执行完毕,返回全部任务的结果值。
    • T invokeAny(Collection> tasks):提交所有可执行的Callable类型任务,第一个任务成功执行后,将其结果作为返回值。
    • T invokeAny(Collection> tasks,long timeout, TimeUnit unit):提交所有可执行的Callable类型任务,第一个任务成功执行后,将其结果作为返回值。设置超时时间,超出最大等待时间,中断剩余未执行的任务,返回当前执行的TimeUnit对象。

 

  • Eexcutors:线程池工厂类,包含诸如RunnableAdapter、PrivilegedCallable等内部类,包含诸多创建线程池的静态方法,返回的线程池都是ExecutorService接口的实现类,可创建ExecutorService、ThreadFactory、Callable类型的对象。创建线程池的实现也是新建ThreaPoolExecutor对象,使用默认的ThreadPoolExecutor构造方法,创建符合业务的线程池。
    • ExecutorService newFixedThreadPool(int nThreads):创建一个在共享无边界队列上运行固定数量线程的线程池,该池上最多有nThread个活动线程,如果在所有线程都活动的情况下提交新的任务,新的任务将在队列中等待线程可用。如果线程池中的某个线程在线程池关闭之前由于失败而终止,则线程池中新的线程将会替代终止的线程继续执行,池中的线程会一直存在,除非显示的调用shutdown()方法。
    • ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory):和上面的静态方法一样,唯一不同就是参数列表中多了ThreadFactory对象。
    • ExecutorService newSingleThreadExecutor():创建线程数为1的线程池,在任意的时间内只有一个任务在执行,如果该任务在执行过程中失败而终止了,则需要在后续执行中将其替换为新任务。
    • ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory):创建线程数为1的线程池,和上面方法作用一直,在需要的时候传递ThreadFactory对象创建新线程。
    • ExecutorService newCachedThreadPool():创建一个可缓存的线程池,调用execute将重用之前构造的可用线程,如果没有现有线程可用,则将创建新的线程并将其添加进池中,超过默认时间未使用的线程将被终止并从缓存中移除,因此,空闲时间足够长的池不会消耗任何资源。
    • ExecutorService newCachedThreadPool(ThreadFactory threadFactory):作用和上面方法一样,在需要的时候传递ThreadFactory对象创建新的线程。
    • ScheduledExecutorService newSingleThreadScheduledExecutor():创建线程数为1的线程池,可以延迟执行,通过新建ScheduledThreadPoolExecutor对象返回线程池对象。
    • ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory):创建线程数为1的线程池,可以延迟执行,通过新建ScheduledThreadPoolExecutor对象返回线程池对象,在需要的时候传递ThreadFactory对象创建新的线程。
    • ScheduledExecutorService newScheduledThreadPool(int corePoolSize):创建指定线程数量的线程池,可以在指定的时间执行,也可以周期性的执行。
    • ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory):创建指定线程数量的线程池,可以在指定的时间执行,也可以周期性的执行,在需要的时候传递ThreadFactory对象创建新的线程。
    • callable(Object o):参数可以传入Runnable、PrivilegedAction、PrivilegedExceptionAction等对象,返回Callable对象。
    • Callable privilegedCallable(Callable callable):返回 Callable 对象,调用它时可在当前的访问控制上下文中执行给定的 callable 对象。
    • Callable privilegedCallableUsingCurrentClassLoader(Callable callable):返回 Callable 对象,调用它时可在当前的访问控制上下文中,使用当前上下文类加载器作为上下文类加载器来执行给定的 callable 对象。
    • jdk1.8新增的几个方法:
      • ExecutorService newWorkStealingPool(int parallelism):创建一个指定线程数的线程池,返回ForkJoinPool对象,该对象是从1.7添加的,继承了ExecutorService,是对ExecutorService的补充,主要是为了实现“分而治之”的算法,特别是分治之后递归调用的函数,最适合于计算密集型的任务,
      • ExecutorService newWorkStealingPool():和上面方法一样,只是没有指定线程数。
  • ThreaPoolExecutor:线程池的实现,继承了AbstractExecutorService类,该类实现了ExecutorService接口,Executors中静态方法创建线程池大致使用该对象的构造方法,通过改变构造参数来创建不同使用场景的线程池,基本的构造方法如下
    /**
     * 
     * @param corePoolSize:保留在线程池中的数量
     * @param maximumPoolSize:线程池中最大的线程数
     * @param keepAliveTime:当目前线程数大于最大线程数时,新的线程加入线程池最大等待时间。
     * @param unit:超时时间单位,与keepAliveTime共同决定最大超时时间
     * @param workQueue:用于任务执行之前保存任务的队列,只包含使用execute()方法提交的任务。
     * @param threadFactory:线程工厂类,用于在需要的时候生成新的线程,默认是实现Executors.
     *                       defaultThreadFactory(),即new一个Thread对象,设置线程名称,
    *                       daemon等属性
    * @param handler:当线程边界和队列容量已达而阻止执行时要是用的处理程序,也就是当提交任务
    *                 时,目前的线程池中已无空闲线程、队列也满了,就会调用handler的
    *                 rejectedExecution方法。
    */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue 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;
    }

    如上所示,构造函数中的corePoolSize、maximumPoolSize、keepAliveTime、threadFactory、handler几个属性,在ThreadPoolExecutor中都是使用了valatile关键字修饰,获得原子性,保证了在并发环境下,这几个对象能有正确的表现。

    在ThreadPoolExecutor中使用了一些常量去保存线程池运行时的状态,存储在高阶位,在运行时也使用了一些方法根据不同的运行时状态改变常量

    // runState is stored in the high-order bits
    //状态常量
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;
    
    //Packing and unpacking ctl
    //包厢开箱控制
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    private static int ctlOf(int rs, int wc) { return rs | wc; }

    在ThreaPoolExecutor中还存在构造函数的多重表现,上面展示的是其余构造函数调用的根本方法,其余的表现形式如下

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
    
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }

     

     

     

     

 

你可能感兴趣的:(java,java)