当线程池中线程数量大于corePoolSize的时候。
-unit(TimeUnit枚举类):上面参数时间的单位,可以是分钟,秒,毫秒等等。
-workQueue(BlockingQueue):任务队列,当线程任务提交到线程池以后,首先放入队列中,然后线程池按照该任务队列依次执行相应的任务。可以使用的workQueue有很多,比如:LinkedBlockingQueue等等。
-threadFactory(ThreadFactory类):新线程产生工厂类。
-handler(RejectedExecutionHandler类):当提交线程拒绝执行、异常的时候,处理异常的类。该类取值如下:(注意都是内部类)
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务,重复此过程。
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务。? 除了自定义线程池以外, java提供了几种常用的线程池,可以快捷的供程序员使用,他们分别是:
1、newFixedThreadPool 创建固定大小数量线程池,数量通过传入的参数决定。
2、newSingleThreadExecutor 创建一个线程容量的线程池,所有的线程依次执行,相当于创建固定数量为1的线程池。
3、newCachedThreadPool 创建可缓存的线程池,没有最大线程限制(实际上是Integer.MAX_VALUE)。如果用空闲线程等待时间超过一分钟,就关闭该线程。
4、newScheduledThreadPool 创建计划(延迟)任务线程池,线程池中的线程可以让其在特定的延迟时间之后执行,也可以以固定的时间重复执行(周期性执行)。相当于以前的Timer类的使用。
5、newSingleThreadScheduledExecutor 创建单线程池延迟任务,创建一个线程容量的计划任务。
? ? 其实通过静态方法创建的上面几种线程池,也都是通过传入默认的各个参数,然后返回一个有各自特点的线程池。具体参数可以通过查看jdk源码阅读。
? ? 有了线程池,那么我们如何利用线程池中线程执行我们的任务,由于Java将线程池的封装,我们拿到的线程池的线程其实是一个包含线程任务的执行器,只需要调运执行器的执行方法,就会自动执行我们线程中的任务。对于非计划任务,我们需要拿到一个ThreadPoolExecutor,对于计划任务,我们需要拿到一个ScheduledThreadPoolExecutor(它是ThreadPoolExecutor的子类)。在了解这两个类之前,需要先了解两个接口,ExecutorService以及它的子接口ScheduleThreadExecutorService接口,上面两个接口分别实现了这两个接口,这个两接口定义了execute(Runnable r)方法,这个方法去执行线程的任务。也就是我们通过调运ThreadPoolExecutor或者ScheduledThreadPoolExecutor的execute(Runnable r)方法开启我们的线程,并且执行我们的线程任务,具体代码如下:
定义一个单例的线程池:
public class MyPool
{
? ? private static MyPool myPool = null;
? ? //单例线程池中有两种具体的线程池
? ? private ThreadPoolExecutor threadPool = null;
? ? private ScheduledThreadPoolExecutor scheduledPool = null;
?
? ? public ThreadPoolExecutor getThreadPool()
? ? {
? ? ? ? return threadPool;
? ? }
?
? ? public ScheduledThreadPoolExecutor getScheduledPool()
? ? {
? ? ? ? return scheduledPool;
? ? }
?
? ? //设置线程池的各个参数的大小
? ? private int corePoolSize = 10;// 池中所保存的线程数,包括空闲线程。
? ? private int maximumPoolSize = 20;// 池中允许的最大线程数。
? ? private long keepAliveTime = 3;// 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
? ? private int scheduledPoolSize = 10;
?
? ? private static synchronized void create()
? ? {
? ? ? ? if (myPool == null)
? ? ? ? ? ? myPool = new MyPool();
? ? }
?
? ? public static MyPool getInstance()
? ? {
? ? ? ? if (myPool == null)
? ? ? ? ? ? create();
? ? ? ? return myPool;
? ? }
?
? ? private MyPool()
? ? {
? ? ? ? //实例化线程池,这里使用的LinkedBlockingQueue作为workQueue,使用DiscardOldestPolicy作为handler
? ? ? ? this.threadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
? ? ? ? ? ? ? ? keepAliveTime, TimeUnit.SECONDS,
? ? ? ? ? ? ? ? new LinkedBlockingQueue(),
? ? ? ? ? ? ? ? new ThreadPoolExecutor.DiscardOldestPolicy());
? ? ? ? //实例化计划任务线程池
? ? ? ? this.scheduledPool = new ScheduledThreadPoolExecutor(scheduledPoolSize);
? ? }
}
获取线程池中的线程,并且执行线程中任务:
@Test
public void testThreadPool()
{
?
? ? ThreadPoolExecutor pool1 = (ThreadPoolExecutor) Executors
? ? ? ? ? ? .newCachedThreadPool();
? ? pool1.execute(new Runnable()
? ? {
?
? ? ? ? @Override
? ? ? ? public void run()
? ? ? ? {
? ? ? ? ? ? System.out.println("快捷线程池中的线程!");
? ? ? ? }
? ? });
?
? ? ThreadPoolExecutor pool2 = MyPool.getInstance().getThreadPool();
? ? pool2.execute(new Runnable()
? ? {
?
? ? ? ? @Override
? ? ? ? public void run()
? ? ? ? {
? ? ? ? ? ? System.out.println("普通线程池中的线程");
? ? ? ? }
? ? });
?
? ? Scheduled