ThreadPoolExecutor线程池的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ab7253957/article/details/78590614
package com.jrq.core.file.executor;

import com.google.common.util.concurrent.*;

import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public final class ExecutorServiceManager {

    private static final ListeningExecutorService executorService =
            MoreExecutors.listeningDecorator(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()));

    private ExecutorServiceManager() {
    }

    /**
     * 添加回调
     *
     * @param future
     * @param callback
     */
    public static void addCallback(ListenableFuture future, FutureCallback callback) {
        Futures.addCallback(future, callback, executorService);
    }

    /**
     * 执行任务 有返回值
     *
     * @param task
     * @return
     */
    public static ListenableFuture submit(Callable task) {
        return executorService.submit(task);
    }

    /**
     * 执行任务 无返回值
     *
     * @param task
     */
    public static void execute(Runnable task) {
        executorService.execute(task);
    }
}


      我们看上面这样一段代码,使用了ThreadPoolExecutor创建了一个单线程的线程池,另外我使用了google的并发包guava进行修饰,guava有什么好处?可以添加回调函数,功能似乎更强大;另外喜欢用google的东西,guava这个工具包真实不错

     其实可以使用Executors来创建线程池,类似于这样Executors.newSingleThreadExecutor(),不过现在正在使用阿里Java编程规约,提倡使用ThreadPoolExecutor创建线程池,可以规避风险,了解线程线程池的原理,没错没错,不然就没有这篇文章了,我们的主要任务就是学习ThreadPoolExecutor构造方法的参数,另外喜欢用阿里的东西

  

ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue)
 

corePoolSize:核心线程数
maximumPoolSize:最大线程数

keepAliveTime:存活时间

unit:keepAliveTime的时间单位-TimeUnit.MILLISECONDS(毫秒级别)

workQueue:阻塞队列
  详细说一下阻塞队列,有四种队列形式都实现了BlockingQueue接口

1.ArrayBlockingQueue 有界队列(数组),意思是可保存的任务是有限的,需要初始化大小

2.LinkedBlockingQueue 无界队列,使用链表,意思是任务可无限添加

3.SynchronousQueue 直接提交,不对任务进行保存

    队列的选择关系到线程数的设定,

例:

1.Executors.newSingleThreadExecutor()静态方法

new ThreadPoolExecutor(1, 1,  0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())
创建了一个单线程的线程池,corePoolSize 和 maximumPoolSize都设置为1,意思是线程池中只会有一个线程,此时keepAliveTime这个参数是无效的,因为没有创建corePoolSize线程数之外的线程,这种情况下任务将无限添加到队列

2.Executors.newCachedThreadPool()静态方法

new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>())

直接提交队列,核心线程数为0,最大线程数为Integer.MAX_VALUE,存活时间60秒,这种情况下任务并发时将无限创建线程,当线程空闲60秒即会被回收,回收到corePoolSize线程数,此处这个值为0,也就是说最后可能所有的线程都会被消灭

3.Executors.newFixedThreadPool(10)静态方法

new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>())

创建固定线程数的线程,队列无限增长,这种方式创建的线程池和单线程线程池是同个道理

总而言之,队列的选择和线程数要要合理




猜你喜欢

转载自blog.csdn.net/ab7253957/article/details/78590614