Java教程

java(2) 多线程

本文主要是介绍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》
未完待续。。

这篇关于java(2) 多线程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!