java(2) 多线程

五.线程池

线程池是为了提高由于频繁创建线程而大大降低的系统效率,如果并发的线程很多,并且每个线程都执行了一个时间很短的任务就结束了,因为频繁创建线程和销毁线程需要时间,线程池使线程可以复用,就是执行完一个任务不被销毁,继续执行其他的任务。

①.继承实现

从最核心的ThreadPoolExecutor类开始,ThreadPoolExecutor继承于AbstractExecutorService抽象类,

AbstractExecutorService抽象类实现了ExecutorService接口,ExecutorService实现了Executor接口,

Executor中定义了关键方法:

void execute(Runnable command);

ExecutorService接口中新定义了很多方法:

void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);

AbstractExecutorService抽象类中实现了ExecutorService接口中的submit的不同参数的三个方法,

并且新加入了一些方法

ThreadPoolExecutor类中,直接使用的父类(AbstractExecutorService)的方法,未复写submit(),但是实现了shutdown(),shutdownNow(),execute(…);

submit()方法根本上也是使用execute(…)方法去执行线程的。submit()方法会有一个Future接口类型的返回值;

public void shutdown() {}
public List<Runnable> shutdownNow(){}
public void execute(Runnable command){}

/*
*submit()方法(其一)
*/
public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }

②.构造方法

ThreadPoolExecutor有四个参数不同的构造方法,其实都是用参数最多的那个构造方法去构造的;

ThreadPoolExecutor(int,int,long,TimeUnit,BlockingQueue<Runnable>);
ThreadPoolExecutor(int,int,long,TimeUnit,BlockingQueue<Runnable>,ThreadFactory);
ThreadPoolExecutor(int,int,long,TimeUnit,BlockingQueue<Runnable>,RejectedExecutionHandler);
ThreadPoolExecutor(int,int,long,TimeUnit,BlockingQueue<Runnable>
						,ThreadFactory,RejectedExecutionHandler);
						
/*
*五个参数的构造方法
*/	
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    
    拿第一个举例,看到其实是调用了七个参数的构造方法,使用默认的ThreadFactory和拒绝策略。

参数含义:

参数 使用
corePoolSize 留在池中的线程数,即使它们是空闲的,除非{@code allowCoreThreadTimeOut}设置 这个参数是否生效取决于allowCoreThreadTimeOut变量的值,该变量默认是false,即对于核心线程没有超时限制,所以这种情况下,corePoolSize参数是起效的。
如果allowCoreThreadTimeOut为true,那么核心线程允许超时,并且超时时间就是keepAliveTime参数和unit共同决定的值,这种情况下,如果线程池长时间空闲的话最终存活的线程会变为0,也即corePoolSize参数失效。
maximumPoolSize 池中允许的最大线程数 线程池中最大的存活线程数。这个参数比较好理解,对于超出corePoolSize部分的线程,无论allowCoreThreadTimeOut变量的值是true还是false,都会超时,超时时间由keepAliveTime和unit两个参数算出。
keepAliveTime 当线程数大于核心数时,这是多余的空闲线程在终止之前等待新任务的最大时间。 超时时间。
unit {@code keepAliveTime}参数的时间单位 超时时间的单位(TimeUnit类中有7种静态属性),天,小时,分,秒,毫秒,微秒,纳秒等,与keepAliveTime参数共同决定超时时间。
workQueue 用于在任务执行之前保存它们的队列。这个队列将只保存由{@code execute}方法提交的{@code Runnable}任务。 当调用execute方法时,如果线程池中没有空闲的可用线程,那么就会把这个Runnable对象放到该队列中。这个参数必须是一个实现BlockingQueue接口的阻塞队列,因为要保证线程安全。
有一个要注意的点是,只有调用execute方法,才会向这个队列中添加任务,submit方法提交任务时,如果没有可用的线程也不会直接扔掉,AbstractExecutorService类中对submit方法的实现,submit方法只是把传进来的Runnable对象或Callable对象包装成一个新的Runnable对象,然后调用execute方法,并将包装后的FutureTask对象作为一个Future引用返回给调用者。Future的阻塞特性实际是在FutureTask中实现的。
threadFactory 执行程序创建新线程时要使用的工厂 线程工厂类。用于在需要的时候生成新的线程。默认实现是Executors.defaultThreadFactory(),即new 一个Thread对象,并设置线程名称,daemon等属性。
handler 当执行因达到线程边界和队列容量而阻塞时要使用的处理程序 表示当拒绝处理任务时的策略,有以下四种取值:
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

③比较重要的几个方法

方法 参数/返回值
execute() Runnable command / void 在Executor接口中声明,
ThreadPoolExecutor中实现,
是ThreadPoolExecutor的核心方法,
通过这个方法可以提交一个任务给线程池,由线程池去执行。
submit() Runnable task / Future<?>
Runnable task, T result / Future
Callable task / Future
在ExecutorService中声明,在AbstractExecutorService中实现,通过这个方法可以提交一个任务给线程池,但是和execute()有区别,可以通过Future类型拿到返回值。
shutdown() void / void 启动一个有序的关闭,先前提交的任务将被执行,但不接受新的任务。如果已经关闭,则调用没有额外效果。
shutdownNow() void / List 尝试停止所有正在执行的任务,停止正在等待的任务的处理,并返回正在等待执行的任务的列表。当从这个方法返回时,这些任务将从任务队列中被排干(删除)。

参考《https://blog.csdn.net/zhuge134/article/details/88376764》
未完待续。。

上一篇:sqli-labs(11-20)


下一篇:记录一次使用validate,并将验证错误结果返回给前端