一、FixedThreadPool、CachedThreadPool、SingleThreadExecutor、ScheduledThreadPool 简单使用(不推荐)
public void fixedThreadPool1(){
int size = 5;
ExecutorService threadPool = Executors.newFixedThreadPool(size);
// ExecutorService threadPool = Executors.newCachedThreadPool(); //缓存,同上
// ExecutorService threadPool = Executors.newSingleThreadExecutor(); //单线程
// ExecutorService threadPool = Executors.newScheduledThreadPool(size); //
while (size>0) {
threadPool.execute(new MyRunnable());
size--;
}
threadPool.shutdown();
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"运行了");
}
}
不推荐原因:
1)newFixedThreadPool和newSingleThreadExecutor:
主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
2)newCachedThreadPool和newScheduledThreadPool:
主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。
二、ExecutorService、ThreadPoolExecutor实例化用法(阿里巴巴规范)【推荐】
原理:使用第三方线程工厂,com.google.guava包
com.google.guava
guava
27.0.1-jre
public void alibabaThreadPool(){
//线程池核心池的大小
int corePoolSize = 5;
//线程池的最大线程数
int maximumPoolSize = 200;
//当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间
long keepAliveTime = 0L;
//keepAliveTime 的时间单位
TimeUnit unit = TimeUnit.MILLISECONDS;
//用来储存等待执行任务的队列
BlockingQueue workQueue = new LinkedBlockingQueue(1024);
//线程工厂,使用com.google.guava包
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("my-pool-%d").build();
//拒绝策略
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
ExecutorService threadPool = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,threadFactory,handler);
//这里为了备注各参数用途,就没有像下面优雅编写
/*ExecutorService threadPool = new ThreadPoolExecutor(5,200,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue(1024),
new ThreadFactoryBuilder().setNameFormat("my-pool-%d").build(),new ThreadPoolExecutor.AbortPolicy());*/
while (corePoolSize>0) {
threadPool.execute(new MyRunnable());
corePoolSize--;
}
threadPool.shutdown();
}
三、Future、Callable有返回值,get()阻塞串行
原理:Future是ExecutorService 调用submit()返回的结果集(泛型),实现Callable接口,支持线程执行完返回结果。
/***
* 有返回,串行
* @throws Exception
*/
public void alibabaThreadPool2() throws Exception{
int corePoolSize = 5;
ExecutorService threadPool = new ThreadPoolExecutor(corePoolSize,200,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue(1024),
new ThreadFactoryBuilder().setNameFormat("my-pool-%d").build(),new ThreadPoolExecutor.AbortPolicy());
while (corePoolSize>0) {
try {
Future future = threadPool.submit(new MyCallable());
Map map = (Map) future.get(); //会阻塞(串行)
System.out.println("返回:" + map.get("back"));
System.out.println("----------------华丽的分割线-------------------");
}catch (InterruptedException e){
e.printStackTrace();
}catch (ExecutionException e){
e.printStackTrace();
}
corePoolSize--;
}
threadPool.shutdown();
}
class MyCallable implements Callable
四、Future、Callable支持返回,并行
/***
* 有返回,并行
* @throws Exception
*/
public void alibabaThreadPool3() throws Exception{
//线程池核心池的大小
int corePoolSize = 5;
ExecutorService threadPool = new ThreadPoolExecutor(corePoolSize,200,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue(1024),
new ThreadFactoryBuilder().setNameFormat("my-pool-%d").build(),new ThreadPoolExecutor.AbortPolicy());
List list = new ArrayList<>();
while (corePoolSize>0) {
Future future = threadPool.submit(new MyCallable());
list.add(future);
corePoolSize--;
}
for(Future future : list){
Map map = (Map) future.get();
System.out.println("返回:" + map.get("back"));
}
threadPool.shutdown();
}
五、CyclicBarrier、Runnable同时并行
原理:Runnable实现类添加CyclicBarrier实例做成员变量,实例化是导入。run()方法前置调用cyclicBarrier.await() 等待所有线程准备就绪再同时执行。
/***
* CyclicBarrier同时并行,一般用来测试并发
* @throws Exception
*/
public void alibabaThreadPool4() throws Exception{
//线程池核心池的大小
int corePoolSize = 100;
ExecutorService threadPool = new ThreadPoolExecutor(corePoolSize,200,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue(1024),
new ThreadFactoryBuilder().setNameFormat("my-pool-%d").build(),new ThreadPoolExecutor.AbortPolicy());
//注意cyclicBarrier对象不能在循环里面多次new,线程会挂,同时平时开发可以共享的尽量不要在循环里去new,影响性能
CyclicBarrier cyclicBarrier = new CyclicBarrier(corePoolSize);
for (int i = 0; i < corePoolSize; i++) {
threadPool.execute(new MyRunnable2(cyclicBarrier));
}
threadPool.shutdown();
}
class MyRunnable2 implements Runnable {
private CyclicBarrier cyclicBarrier;
public MyRunnable2(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
// 等待所有任务准备就绪
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName()+"开始时间:" +
DateFormat.getTimeInstance().format(new Date()));
int rand = new Random().nextInt(5)*1000;
System.out.println(Thread.currentThread().getName()+"睡眠"+rand);
Thread.sleep(rand);
// 测试内容
System.out.println(Thread.currentThread().getName());
System.out.println(Thread.currentThread().getName()+"结束时间:" +
DateFormat.getTimeInstance().format(new Date()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
五、CyclicBarrier、Callable同时并行,支持返回
原理:Callable实现类添加CyclicBarrier实例做成员变量,实例化是导入。call()方法前置调用cyclicBarrier.await() 等待所有线程准备就绪再同时执行。
/***
* 有返回,CyclicBarrier同时并行,一般用来测试并发
* @throws Exception
*/
public void alibabaThreadPool5() throws Exception{
//线程池核心池的大小
int corePoolSize = 5;
ExecutorService threadPool = new ThreadPoolExecutor(corePoolSize,200,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue(1024),
new ThreadFactoryBuilder().setNameFormat("my-pool-%d").build(),new ThreadPoolExecutor.AbortPolicy());
List list = new ArrayList<>();
//注意cyclicBarrier对象不能在循环里面多次new,线程会挂,同时平时开发可以共享的尽量不要在循环里去new,影响性能
CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
while (corePoolSize>0) {
System.out.println(corePoolSize+"开始:" +
DateFormat.getTimeInstance().format(new Date()));
Future future = threadPool.submit(new MyCallable2(cyclicBarrier));
list.add(future);
System.out.println(corePoolSize+"结束:" +
DateFormat.getTimeInstance().format(new Date()));
corePoolSize--;
}
for(Future future : list){
Map map = (Map) future.get();
System.out.println("返回:" + map.get("back"));
}
threadPool.shutdown();
}
class MyCallable2 implements Callable
六、ScheduledExecutorService、ScheduledThreadPoolExecutor 支持时间调度,定时任务
原理:使用第三方线程工厂,commons-lang3包
org.apache.commons
commons-lang3
3.8.1
public void scheduledThreadPool(){
//线程池核心池的大小
int corePoolSize = 2;
//线程工厂,使用commons-lang3包
// ThreadFactory threadFactory1 = new BasicThreadFactory.Builder().namingPattern("my-schedule-pool-%d").daemon(true).build(); //设置守护进程,调度有问题
ThreadFactory threadFactory = new BasicThreadFactory.Builder().namingPattern("my-schedule-pool-%d").build();
ScheduledExecutorService threadPool = new ScheduledThreadPoolExecutor(corePoolSize,threadFactory);
// ScheduledExecutorService threadPool = new ScheduledThreadPoolExecutor(corePoolSize);
// scheduleAtFixedRate(threadPool,1000);
// scheduleAtFixedRate(threadPool,5000);
scheduleWithFixedDelay(threadPool,"2019-03-09 14:09:50");
scheduleWithFixedDelay(threadPool,"2019-03-09 14:02:30");
}
private void scheduleAtFixedRate(ScheduledExecutorService service, final int sleepTime){
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
long start = System.currentTimeMillis();
System.out.println("scheduleAtFixedRate 开始时间:" +
DateFormat.getTimeInstance().format(new Date()));
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("scheduleAtFixedRate 消耗时间:" + (end -start)/1000 + "m");
System.out.println("scheduleAtFixedRate 完成时间:"
+ DateFormat.getTimeInstance().format(new Date()));
System.out.println("----------------华丽的分割线-------------------");
}
},1000,5000,TimeUnit.MILLISECONDS);
}
private static void scheduleWithFixedDelay(ScheduledExecutorService service,String time){
long delay = 5000;
long initDelay = getTimeMillis(time) - System.currentTimeMillis();
System.out.println(getTimeMillis(time));
System.out.println(System.currentTimeMillis());
System.out.println(initDelay);
initDelay = initDelay > 0 ? initDelay : delay + initDelay;
service.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":"+DateFormat.getTimeInstance().format(new Date()));
}
},initDelay,delay,TimeUnit.MILLISECONDS);
}
private static long getTimeMillis(String time) {
return (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).parse(time, new ParsePosition(0)).getTime();
}
七、ThreadPoolExecutor、ScheduledThreadPoolExecutor实例化参数用法详析
new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
keepAliveTime, milliseconds,runnableTaskQueue, threadFactory,handler);
new ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory);
线程池原理可阅读我另一篇博客
谈谈对 java线程池(Executors、ExecutorService、ScheduledExecutorService)和(Callable、Future、CyclicBarrier)的理解