线程池的做用:java
线程池做用就是限制系统中执行线程的数量。
根据系统的环境状况,能够自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了形成系统拥挤效率不高。用线程池控制线程数量,其余线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务须要运行时,若是线程池中有等待的工做线程,就能够开始运行了;不然进入等待队列。编程
为何要用线程池:服务器
ThreadGroup与ThreadPoolExecutor的区别多线程
我本身的理解也是一直觉得ThreadGroup就是ThreadPoolExecutor(线程池),这是一个很是大的误会,最近把二者仔细分析了下。线程组表示一个线程的集合。此外,线程组也能够包含其余线程组。线程组构成一棵树,在树中,除了初始线程组外,每一个线程组都有一个父线程组。容许线程访问有关本身的线程组的信息,可是不容许它访问有关其线程组的父线程组或其余任何线程组的信息;线程消耗包括内存和其它系统资源在内的大量资源。除了 Thread 对象所需的内存以外,每一个线程都须要两个可能很大的执行调用堆栈。除此之外,JVM 可能会为每一个 Java线程建立一个本机线程,这些本机线程将消耗额外的系统资源。最后,虽然线程之间切换的调度开销很小,但若是有不少线程,环境切换也可能严重地影响程序的性能。线程池是由于线程的生成关闭很浪费资源 因此不要频繁的操做 线程次 就是管理线程的地方 不用了它可让它休眠也就是他替你管理线程 并且比你管理的要好的多。线程池为线程生命周期开销问题和资源不足问题提供了解决方案。经过对多个任务重用线程,线程建立的开销被分摊到了多个任务上。其好处是,由于在请求到达时线程已经存在,因此无心中也消除了线程建立所带来的延迟。这样,就能够当即为请求服务,使应用程序响应更快。并且,经过适当地调整线程池中的线程数目,也就是当请求的数目超过某个阈值时,就强制其它任何新到的请求一直等待,直到得到一个线程来处理为止,从而能够防止资源不足。app
Executor详解:ide
Java里面线程池的顶级接口是Executor,可是严格意义上讲Executor并非一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。ThreadPoolExecutor是Executors类的底层实现。咱们先介绍下Executors。工具
Sun在Java5中,对Java线程的类库作了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池以外,还有不少多线程相关的内容,为多线程的编程带来了极大便利。为了编写高效稳定可靠的多线程程序,线程部分的新增内容显得尤其重要。
有关Java5线程新特征的内容所有在java.util.concurrent下面,里面包含数目众多的接口和类,熟悉这部分API特征是一项艰难的学习过程。目前有关这方面的资料和书籍都少之又少,大所属介绍线程方面书籍还停留在java5以前的知识层面上。
固然新特征对作多线程程序没有必须的关系,在java5以前通用能够写出很优秀的多线程程序。只是代价不同而已。
线程池的基本思想仍是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样能够避免反复建立线程对象所带来的性能开销,节省了系统的资源。
在Java5以前,要实现一个线程池是至关有难度的,如今Java5为咱们作好了一切,咱们只须要按照提供的API来使用,便可享受线程池带来的极大便利。
Java5的线程池分好多种:固定尺寸的线程池、可变尺寸链接池。
在使用线程池以前,必须知道如何去建立一个线程池,在Java5中,须要了解的是java.util.concurrent.Executors类的API,这个类提供大量建立链接池的静态方法,是必须掌握的。性能
实例:学习
1、固定大小的线程池
spa
Java代码
[java] view plain copy
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
Process finished with exit code 0
2、单任务线程池
在上例的基础上改一行建立pool对象的代码为:
//建立一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。
Java代码
[java] view plain copy
输出结果为:
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
Process finished with exit code 0
对于以上两种链接池,大小都是固定的,当要加入的池的线程(或者任务)超过池最大尺寸时候,则入此线程池须要排队等待。
一旦池中有线程完毕,则排队等待的某个线程会入池执行。
3、可变尺寸的线程池
与上面的相似,只是改动下pool的建立方式:
//建立一个可根据须要建立新线程的线程池,可是在之前构造的线程可用时将重用它们。
Java代码
[java] view plain copy
pool-1-thread-5正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-4正在执行。。。
pool-1-thread-3正在执行。。。
pool-1-thread-2正在执行。。。
Process finished with exit code 0
4、延迟链接池
Java代码
[java] view plain copy
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
Process finished with exit code 0
5、单任务延迟链接池
在四代码基础上,作改动
//建立一个单线程执行程序,它可安排在给定延迟后运行命令或者按期地执行。
Java代码
[java] view plain copy
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
Process finished with exit code 0
6、自定义线程池
Java代码
[java] view plain copy
pool-1-thread-1正在执行。。。 pool-1-thread-2正在执行。。。 pool-1-thread-2正在执行。。。 pool-1-thread-1正在执行。。。 pool-1-thread-2正在执行。。。 pool-1-thread-1正在执行。。。 pool-1-thread-2正在执行。。。 Process finished with exit code 0 建立自定义线程池的构造方法不少,本例中参数的含义以下: ThreadPoolExecutor public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) 用给定的初始参数和默认的线程工厂及处理程序建立新的 ThreadPoolExecutor。使用 Executors 工厂方法之一比使用此通用构造方法方便得多。 参数: corePoolSize - 池中所保存的线程数,包括空闲线程。 maximumPoolSize - 池中容许的最大线程数。 keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。 unit - keepAliveTime 参数的时间单位。 workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任务。 抛出: IllegalArgumentException - 若是 corePoolSize 或 keepAliveTime 小于零,或者 maximumPoolSize 小于或等于零,或者 corePoolSize 大于 maximumPoolSize。 NullPointerException - 若是 workQueue 为 null 自定义链接池稍微麻烦些,不过经过建立的ThreadPoolExecutor线程池对象,能够获取到当前线程池的尺寸、正在执行任务的线程数、工做队列等等。