当创建线程和销毁线程的时间远大于线程执行任务的时间,就可以考虑用线程池来提升性能。合理利用线程池能够带来三个好处。第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行,即在处理任务前的准备阶段,程序的开始阶段就准备好线程池。第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
SingleThreadExecutor:单个后台线程 (其缓冲队列是LinkedBlockingQueue,无界的)。此线程池保证所有任务的执行顺序按照任务的提交顺序执行.
创建一个线程池,它可以安排任务在给定时间的延迟之后运行该命令,或定时执行。
创建一个线程池,根据需要创建新线程,但是将重写之前线程池的构造。
这个线程池通常会提高性能去执行许多短期异步任务的程序。
如果有可用线程,当线程池调用execute, 将重用之前的构造函数。
如果没有现有的线程可用,那么就创建新的线程并添加到池中。
线程没有使用60秒的时间被终止并从线程池里移除缓存。
因此,一个闲置时间足够长的线程池不消耗任何资源。
注意,线程池有类似的属性,但有一些不同的细节(例如,超时参数)可以使用@link ThreadPoolExecutor构造函数创建。
创建一个线程池,使用固定数量的线程在共享的无界队列中操作。
在任何时候,有最多 nThreads(就是我们传入参数的数量)的线程将处理任务。
如果所有线程都处于活动状态时,提交额外的任务,他们会在队列中等待,直到有一个线程可用。
如果在执行过程中出现故障,任何线程都会终止。如果需要执行后续任务,新的任务将取代它的位置。线程池中的线程会一直存在,直到它显式为止(调用shutdown)
nThreads 就是传入线程池的数量 ,当nThreads <= 0 就会抛异常IllegalArgumentException
corePoolSize():核心池,有两个方法preStartCoreThread和preStartAllCoreThread,默认建好的线程池初始线程为0, 只有调用了preStart才会建好初始的线程,不然就是当有任务来之后,才会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中。
execute()向线程池提交一个任务。
这个任务可能是直接调用addWorker或放入workQueue中。
If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
当workQueue也容不下这么多任务时,会尝试继续加线程,失败即reject这个task。
worker的run()会在执行完firstTask后,一直去workQueue中getTask并执行这个task。
submit()这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果
shutdown()和shutdownNow()是用来关闭线程池的。
1:如果线程数量未达到corePoolSize,则新建一个线程(核心线程)执行任务
2:如果线程数量达到了corePools,则将任务移入队列等待
3:如果队列已满,新建线程(非核心线程)执行任务
4:如果队列已满,总线程数又达到了maximumPoolSize,就会由RejectedExecutionHandler抛出异常