网站建设方案策划书ppt,高校网站建设的目的和意义,建设标准 免费下载网站,jsp网站开发详解 pdf为什么要使用线程池#xff1f;
JDK1.5后JUC包添加了线程池相关接口#xff0c;在Java诞生之初并没有线程池这个概念。刚开始Java程序都是自行创建线程去处理任务。随着应用使用的线程越来越多#xff0c;JDK开发者们发现有必要使用一个统一的类来管理这些线程#xff0c;…
为什么要使用线程池
JDK1.5后JUC包添加了线程池相关接口在Java诞生之初并没有线程池这个概念。刚开始Java程序都是自行创建线程去处理任务。随着应用使用的线程越来越多JDK开发者们发现有必要使用一个统一的类来管理这些线程从而有效提高线程的执行效率减少创建、销毁线程的开销。
大量线程的创建、销毁是非常消耗资源的。创建线程需要消耗一定的内存、CPU资源大量的线程也会导致大量的线程上下文切换上下文切换代码也是相当大的过多的线程导致频繁切换更是可能使系统性能急速下降。另外操作系统对每个进程能创建的线程数也是有限制的不可能无限创建。但是大量任务也不可能只在主线程处理吧这样也太慢了。比如下面的例子创建上万的线程每个线程打印一下线程名字观察一下任务管理器CPU直接用完。这只是简单的任务要是复杂长时间的任务整个操作系统可能都会受到影响CPU利用率长时间下不来影响其他程序
public class BadMultiThreadTest {public static void main(String[] args) {Runnable r () - {System.out.println(ThreadName- Thread.currentThread().getName());};//过多创建线程导致系统资源消耗严重for (int i 0; i 10000; i) {Thread thread new Thread(r);thread.start();}}
}线程池就是为了解决上述问题出现的解决问题的思路很清晰就是创建好一定数量的线程有任务来了就用这些线程来执行任务任务过多把池里面的线程都占用了就放队列排队等候其他任务执行一旦有空闲线程就可以从队列里面取出任务并执行。有了可控的线程池系统就不会处于一种可能随时被大量并发导致线程大量创建最终压跨系统的危险中。
如何使用线程池
使用线程池去改造上面的例子
public class MultiThreadPoolTest {public static void main(String[] args) {ExecutorService executorService Executors.newFixedThreadPool(10);for (int i 0; i 10000; i) {executorService.execute(() - {System.out.println(ThreadName- Thread.currentThread().getName());});}}
}
这次再观察任务管理器这次CPU占用不会说飙长而是相对平稳。打印的线程名称就是在ThreadName-pool-1-thread-1到ThreadName-pool-1-thread-10之间变化说明这一万个任务都是这10个线程处理的。
线程池的参数含义
上面的例子简单的使用了Excutors工具类来创建了一个固定线程数的线程池。这个工具类还可以创建单线程线程池、可缓存线程池、定时执行任务的线程池等。这些线程池的创建事实上都是在创建一个ThreadPoolExecutor实例只是通过传递不同参数实现不同的线程池效果而已。如果我们把里面的参数都搞明白我们就可以根据实际需求去自定义线程池实际开发中我们都应该使用自定义的线程池去处理相关业务这样能最大提高线程池使用效率提高系统性能。当然这还得靠我们对业务的理解从而定义出合理的线程池。
通过下面这句代码跟踪源码
Executors.newFixedThreadPool(10);
最终调用的函数如下它包含了线程池的所有参数注释 /*** 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,BlockingQueueRunnable 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时间单位 空闲线程存活时间 workQueue 任务队列 threadFactory 创建线程的工厂类 handler 被拒绝任务处理器
线程池处理任务的流程
看一下下面的流程图就能清晰知道任务从被提交再到被线程池中线程执行的流程了。 如上流程图任务被提交后线程池会检查核心线程数是否满了如果不是则会创建一条核心线程以执行该任务。如果满了则把任务放到阻塞队列中等待有空闲的核心线程来执行任务。阻塞队列如果也满了则需要检查最大核心线程数是否满了如果没满创建非核心线程以执行任务如果满了表示线程池再也没能力去处理该任务了则需要拒绝策略做处理。注意到构建线程池的参数中有keepAliveTime时间单位这两个参数这两个参数正是用于回收非核心线程用的当非核心线程没任务了空闲时间达到keepAliveTime配置的值后将会被线程池销毁以回收一些系统资源。
使用线程池的优点
根据上面可以简略总结出使用线程池的几点优点
解决线程创建、销毁等生命周期系统消耗过大问题。因为线程池中的线程一旦创建过核心线程是会一直驻留在池中待用的这样任务来了后直接可以执行消除了创建线程的系统开销。系统响应更及时使用更丝滑。线程池使得系统可控性更强。它避免了系统资源使用不当导致系统崩溃能更合理的使用CPU和内存资源。