Java并发包(java.util.concurrent)阅读(一)ExecutorService ->ThreadPoolExecutor

原创 2017年03月07日 21:33:30

ExecutorService是继承于Executor。ExecutorService,提供了为异步任务(Runable的实现类)创建Future的方法,用来管理任务执行的状态。而且提供管理终止的方法,导致会拒绝新的任务,他提供了两个关闭的方法,shutdown()(等待堆积的任务处理完后管理),shutdownNow(立即关闭,防止等待任务的执行并试图关闭现在正在运行的任务,并且返回一个List,包含了队列中等待任务),之后经行资源的回收。

下图是concurrent包下面的Executor子类继承/实现的关系图。
这里写图片描述

而ThreadPoolExecutor是JDK提供给ExecutorService的一个现实类,这个也是最常用的,会调用池中的可用线程来处理提交的任务,主要用来处理执行大量异步处理任务的时候,改善性能,减少每个任务的调度开销,并且提供了限制和管理线程的方法。


创建方法
主要的生成的方法是有两类,第一类是调用其构造器经常创建实例,第二就是调用Executors这个类经行创建。

一.调用构造器
先讲解调用构造函数,我挑选一个参数最全的构造器给大家讲解下参数,这样其他的构造器十分容易理解。

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

corePoolSize :直译过来的意思就是核心线程数, 而且会一直存活,即使一直处于空闲状态,线程池也会维护线程的最少数量。
maximumPoolSize:最大线程数,就是这个线程池能够达到的最多线程数
keepAliveTime:最大空闲时间,就是当线程空闲达到一定时候之后,而且当前线程数大于核心线程数,就是关闭该线程
unit: 线程池维护线程所允许的空闲时间的单位、可选参数值为:TimeUnit枚举里面的值
workQueue:工作队列,这个队列用于缓存未执行的任务,这个队列只保存通过{execute}这个方法提交的任务
threadFactory:线程工程,用于生产线程
handler:这个处理器用于当工作队列阻塞(达到最大数量)的时候,来处理任务的策略。 默认值ThreadPoolExecutor.AbortPolicy()。

处理器主要有这几种
* ThreadPoolExecutor.CallerRunsPolicy(),当任务被拒绝的时候,会处理器直接调用run()方法运行,如果线程池已经处于关闭状态,任务会丢失。
* ThreadPoolExecutor.AbortPolicy(),在向线程池提交的任务会被拒绝,并抛出异常。
* ThreadPoolExecutor.DiscardPolicy(),当任务被拒绝的时候 ,在向线程池提交的任务会被丢弃。
* ThreadPoolExecutor.DiscardOldestPolicy(),当任务被拒绝的时候 ,会调用工作队列poll()方法(将队列中头部信息取出并丢弃),再将新的任务通过线程池的execute()将任务插入,如果线程池已经处于关闭状态,任务会丢失。

二.调用工具类
另外比较常用的一个方式是使用Executors这个工具类来创建ExecutorService,在这个工具类中封装了一些常用的创建ExecutorService的方法,讲解下常用的几个方法。

newFixedThreadPool:用创建一个固定的线程池。方法参数有两个,线程数量和线程工厂,底层的队列用的是LinkedBlockingQueue,这个队列容量为Integer.MAX_VALUE。提交的都任务都会堆积在队列中,直到有可用的线程进行消费为止。

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>(),
                                  threadFactory);
}

newCacheThreadPool:用创建一个缓存的线程池。这个线程池会根据需要创建新的线程来处理调度任务,但也会重用之前的创建的线程,减少开销。

//传入一个线程工厂(选填,可以调用重载方法)
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>(),
                                  threadFactory);
}

newSingleThreadExecutor:创建一个一个线程的线程池,保证提交的任务串行化执行,看下代码就发现,方法的返回不等价于newFixedThreadPool(1),这里返回的是FinalizableDelegatedExecutorService,但是再深入的看下这个类的代码就会发现实际执行过程是等价于newFixedThreadPool(1),为什么这么写我现在还没搞明白。

//传入一个线程工厂(选填,可以调用重载方法)
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>(),
                                threadFactory));
}

执行方法

ExecutorService提交单条任务的方法主要有两种,submit和executor。

//Executor接口下的
void execute(Runnable command);

submit方法是Executor接口中定义的方法,只能提交Runnable的任务,方法的返回值是空的。我们无法知道该任务运行情况。

//ExecutorService接口下的
 <T> Future<T> submit(Callable<T> task);//传入一个Callable
 <T> Future<T> submit(Runnable task, T result);//传入一个Runnable,并自己设定Future返回值
 Future<?> submit(Runnable task);//传入一个Runnable,Future返回值为null

submit方法是ExecutorService接口中定义的方法,可以提交Runnable和Callable两种任务,并且调用该方法之后我们可以收到Future这个返回值,可以调用
Future中定义的一些方法来获取任务执行状态,并管理任务。

在看下submit方法在AbstractExecutorService中的实现方法,方法中会先将Callable/Runnable封装成RunnableFuture(实际实例的类是FutureTask),再调用execute,将该任务提交到任务队列中,并将ftask返回出去,提供给我们进行监控管理。

    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();//校验任务是否为空
        RunnableFuture<Void> ftask = newTaskFor(task, null);//为任务创建一个Future,提供给我们管理
        execute(ftask);//调用execute经行执行
        return ftask;//返回
    }

关闭ExecutorService
关闭方法有两个shutdown()和shutdownNow()。
前者是将线程池状态转换到关闭,不接受新的任务进入,关闭空闲线程,但是会继续消费队列中堆积的任务。
后者是线程池状态转换到停止,不接受新的任务进入,关闭全部线程,并把队列中堆积的数据都取出来并返回。

    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;//定义局部变量,将静态变量应用进来,个人觉得是因为,JMM和OOP有一定的差异导致的
        mainLock.lock();//先加锁确保线程安全
        try {
            checkShutdownAccess();//有关安全管理器的一些方法
            advanceRunState(SHUTDOWN);//将状态至为关闭
            interruptIdleWorkers();//中端空闲线程
            onShutdown(); // 为ScheduledThreadPoolExecutor这个类服务,在这里是个空方法
        } finally {
            mainLock.unlock();//解锁
        }
        tryTerminate();//尝试中断
    }
    public List<Runnable> shutdownNow() {
        List<Runnable> tasks;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();//先加锁确保线程安全
        try {
            checkShutdownAccess();//有关安全管理器的一些方法
            advanceRunState(STOP);//将状态至为停止
            interruptWorkers();//中断全部线程,会丢失正在运行的任务
            tasks = drainQueue();//取出队列中堆积的任务
        } finally {
            mainLock.unlock();//解锁
        }
        tryTerminate();//尝试中断
        return tasks;
    }

常用的一些方法主要就是这些。新手写博客,有什么问题麻烦大家给我提一下,谢谢
:)

ASP+JS时的"""

在ASP中basic语句中的字符串中包含JS语句,这时处理起间隔符这特殊的符号确实是件麻烦事,苦于找不到相应的资料,一时间头痛万分.现在好了,总算让我想到了解决的办法,原来我这么"后知后觉"啊,呵呵....
  • mostone
  • mostone
  • 2001-07-12 09:44:00
  • 867

Java并发工具包java.util.concurrent用户指南中英文对照阅读版.pdf[带书签]

  • 2015年03月03日 15:35
  • 1.1MB
  • 下载

Java并发包:ExecutorService和ThreadPoolExecutor

文章译自:http://tutorials.jenkov.com/java-util-concurrent/index.html 抽空翻译了一下这个教程的文章,后面会陆续放出,如有不妥,请批评指正...
  • zxc123e
  • zxc123e
  • 2016-07-12 17:50:16
  • 4255

java中Executor、ExecutorService、ThreadPoolExecutor介绍

源码非常简单,只有一个execute(Runnable command)回调接口  public interface Executor {     /**      * Executes the ...
  • linghu_java
  • linghu_java
  • 2013-12-04 18:12:20
  • 99102

Java并发编程-并发工具包java.util.concurrent使用指南

Java 5 添加了一个新的包到 Java 平台,java.util.concurrent 包。这个包包含有一系列能够让 Java 的并发编程变得更加简单轻松的类。在这个包被添加以前,你需要自己去动手...
  • axi295309066
  • axi295309066
  • 2017-03-24 22:41:04
  • 2645

Java集合及concurrent并发包总结(转)

Java集合及concurrent并发包总结(转)   1.集合包     集合包最常用的有Collection和Map两个接口的实现类,Colleciton用于存放多个单对象,Map用于存放Ke...
  • a724888
  • a724888
  • 2017-03-08 09:46:01
  • 1734

java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例

1、CountDownLatch:一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。2、ThreadPoolExecutor/ExecutorService:线程池,使用...
  • javaloveiphone
  • javaloveiphone
  • 2017-01-25 15:18:23
  • 2544

聊聊高并发(四十)解析java.util.concurrent各个组件(十六) ThreadPoolExecutor源码分析

ThreadPoolExecutor是Executor执行框架最重要的一个实现类,提供了线程池管理和任务管理是两个最基本的能力。这篇通过分析ThreadPoolExecutor的源码来看看如何设计和实...
  • ITer_ZC
  • ITer_ZC
  • 2015-07-16 16:27:08
  • 3338

Java并发:多线程和java.util.concurrent并发包总结

引言前面已经针对Java多线程框架中具体的点介绍了很多了,现在是需要一个概括性总结的时候了,正好从网上找到一张描述java.util.concurrent包组成结构的类图,正好可以对java多线程有一...
  • jiq408694711
  • jiq408694711
  • 2016-04-17 22:13:08
  • 7607

得到 ExecutorService 当前活动的线程数

import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.ut...
  • yingzishizhe
  • yingzishizhe
  • 2013-04-07 22:25:40
  • 21771
收藏助手
不良信息举报
您举报文章:Java并发包(java.util.concurrent)阅读(一)ExecutorService ->ThreadPoolExecutor
举报原因:
原因补充:

(最多只允许输入30个字)