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>())
创建固定线程数的线程,队列无限增长,这种方式创建的线程池和单线程线程池是同个道理
总而言之,队列的选择和线程数要要合理