线程池和自定义线程池总结(java )

为什么要使用线程池

我们想用线程池的时候 会去创建一个线程 ,但是如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,
因为频繁创建线程和销毁线程需要时间,提高响应速度:线程的创建时间为T1,执行时间T2,销毁时,提高线程的可管理性管理。

java提供的四种线程池

newCachedThreadPool :

可缓存线程池,若线程池长度超过处理需要,则回收空线程,否则创建新线程,线程规模可无限大。


ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,
而不用每次新建线程。
newFixedThreadPool :

定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()
newScheduledThreadPool :

定长线程池,支持定时及周期性任务执行,类似Timer。

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
使用实例:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
//表示延迟1秒后每3秒执行一次。
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
    
    
    @Override
    public void run() {
    
    
        System.out.println("delay 1 seconds, and excute every 3 seconds");
    }
}, 1, 3, TimeUnit.SECONDS);
newSingleThreadExecutor :

单线程 的线程池,支持FIFO, LIFO, 优先级策略。

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
通过观察源码,其中四种线程的创建都是创建一个ThreadPoolExecutor。
其中ThreadPoolExecutor是ExecutorService接口的实现类。

经常用的线程池类

1.ThreadPoolExecutor

翻看源码可以看到
ThreadPoolExecutor继承了AbstractExecutorService,
AbstractExecutorService 的实现 源码如下:

public abstract class AbstractExecutorService implements ExecutorService {
    
    
 
     
    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    
     };
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    
     };
    public Future<?> submit(Runnable task) {
    
    };
    public <T> Future<T> submit(Runnable task, T result) {
    
     };
    public <T> Future<T> submit(Callable<T> task) {
    
     };
    private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
                            boolean timed, long nanos)
        throws InterruptedException, ExecutionException, TimeoutException {
    
    
    };
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException {
    
    
    };
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                           long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
    
    
    };
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException {
    
    
    };
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                         long timeout, TimeUnit unit)
        throws InterruptedException {
    
    
    };
}

AbstractExecutorService 又是一个抽象类,它实现了ExecutorService接口。
ExecutorService 又继承 Executor 它的实现如下

public interface ExecutorService extends Executor {
    
    
 
    void shutdown();
    boolean isShutdown();
    boolean isTerminated();
    boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task, T result);
    Future<?> submit(Runnable task);
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;
 
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;
    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

再看下 Executor 的实现

public interface Executor {
    
    
    void execute(Runnable command);
}

这里总结一下 ThreadPoolExecutor、AbstractExecutorService、ExecutorService和Executor几个之间的关系了。
参考这个图 更直观 :
在这里插入图片描述

Executor是一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的;

然后ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等;

抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;然后ThreadPoolExecutor继承了类AbstractExecutorService。

在ThreadPoolExecutor类中有几个非常重要的方法:
execute()
submit()
shutdown()
shutdownNow()

execute()方法实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,交由线程池去执行。

submit()方法是在ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果(Future相关内容将在下一篇讲述)。

shutdown()和shutdownNow()是用来关闭线程池的。

还有很多其他的方法:

比如:getQueue() 、getPoolSize() 、getActiveCount()、getCompletedTaskCount()等获取与线程池相关属性的方法,有兴趣的朋友可以自行查阅API。

java.uitl.concurrent.ThreadPoolExecutor类是线程池中最核心的一个类.
ThreadPoolExecutor类中提供了四个构造方法

public class ThreadPoolExecutor extends AbstractExecutorService {
    
    
    .....
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
        BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
    ...
}

从上面的代码可以得知,ThreadPoolExecutor继承了AbstractExecutorService类,并提供了四个构造器,事实上,通过观察每个构造器的源码具体实现,发现前面三个构造器都是调用的第四个构造器进行的初始化工。

线程池中参数解读

corePoolSize :指的是 核心线程池。指保留的线程池大小(不超过maximumPoolSize值时,线程池中最多有corePoolSize 个线程工作)
 小于corePoolSize ,就会创建新线程,= corePoolSize ,这个任务就会保存到BlockingQueue,如果调用prestartAllCoreThreads()方法就会一次性的启动corePoolSize 个数的线程。
  
 maximumPoolSize 指的是线程池的最大数量(线程池中最大有corePoolSize 个线程可运行)
 
 keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;
 
TimeUnit unit, 存活时间的单位值
unit 可以取的参数 有 7个

TimeUnit.DAYS;               //天
TimeUnit.HOURS;             //小时
TimeUnit.MINUTES;           //分钟
TimeUnit.SECONDS;           //秒
TimeUnit.MILLISECONDS;      //毫秒
TimeUnit.MICROSECONDS;      //微妙
TimeUnit.NANOSECONDS;       //纳秒

BlockingQueue workQueue, 保存任务的阻塞队列
可选择的一般有:
ArrayBlockingQueue; // 基于数组的先进先出队列,此队列创建时
必须指定大小
LinkedBlockingQueue; // 基于链表的先进先出队列,如果创建时没有
指定此队列大小,则默认为Integer.MAX_VALUE;
SynchronousQueue; // 这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务
 ArrayBlockingQueue和PriorityBlockingQueue使用较少,一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。

ThreadFactory threadFactory, 创建线程的工厂,给新建的线程赋予名字
RejectedExecutionHandler handler :饱和策略

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 

AbortPolicy :直接抛出异常,默认;
CallerRunsPolicy:用调用者所在的线程来执行任务
DiscardOldestPolicy:丢弃阻塞队列里最老的任务,队列里最靠前的任务
DiscardPolicy :当前任务直接丢弃

在ThreadPoolExecutor类中有几个非常重要的方法:

execute()
submit()
shutdown()
shutdownNow()

execute()方法实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,交由线程池去执行.

submit 与 execute 的区别

submit()方法是在ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果.

关闭线程池:
 shutdown()和shutdownNow() 的区别

shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务

参考:
https://www.cnblogs.com/dolphin0520/p/3932921.html

猜你喜欢

转载自blog.csdn.net/weixin_43975771/article/details/108034443