多线程并发之线程池Executor
【1】常见接口和实现类
① 什么是线程池
首先可以联想一下数据库连接池,Redis中的pool。
线程池提供了一个线程队列,队列中保存着所有等待状态的线程。避免了创建与销毁额外开销,提高了响应的速度。
② 常见的体系结构
常见的线程池体系结构:
java.util.concurrent.Executor : 负责线程的使用与调度的根接口
|--ExecutorService 子接口: 线程池的主要接口
|--ThreadPoolExecutor 线程池的实现类
|--ScheduledExecutorService 子接口:负责线程的调度
|--ScheduledThreadPoolExecutor :继承 ThreadPoolExecutor, 实现 ScheduledExecutorService
如下图所示:
线程池可以解决两个不同问题:由于减少了每个任务调用的开销,它们通常可以在执行大量异步任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行任务集时使用的线程)的方法。每个ThreadPoolExecutor 还维护着一些基本的统计数据,如完成的任务数。
③ 线程池的创建
为了便于跨大量上下文使用,此类提供了很多可调整的参数和扩展钩子(hook)。但是,强烈建议程序员使用较为方便的Executors 工厂方法:
- Executors.newCachedThreadPool()(无界线程池,可以进行自动线程回收)
- Executors.newFixedThreadPool(int)(固定大小线程池)
- Executors.newSingleThreadExecutor()(单个后台线程)
- Executors.newScheduledThreadPool() : 创建固定大小的线程,可以延迟或定时的执行任务。
需要注意的是,它们均为大多数使用场景预定义了设置,也就是说通常情况下可以直接使用无需额外配置。
【2】线程池使用实例
线程池提交任务的三个方法:
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);
实例代码如下:
package com.jane.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* Created by Janus on 2018/9/28.
*/
public class TestThreadPool {
public static void main(String[] args) throws Exception {
//1.创建线程池
ExecutorService pool = Executors.newFixedThreadPool(5);
//参数为Runnable
ThreadPoolRunnable threadPoolRunnable = new ThreadPoolRunnable();
// 2.为线程池中的线程分配任务
// for (int i = 0; i <10 ; i++) {
// pool.submit(threadPoolRunnable);
// }
//参数为Callable
ThreadPoolCallable threadPoolCallable = new ThreadPoolCallable();
List<Future<Integer>> futures = new ArrayList<>();
for (int i = 0; i <10 ; i++) {
Future<Integer> future = pool.submit(threadPoolCallable);
futures.add(future);
}
for (Future<Integer> future : futures) {
System.out.println(future.get());
}
//3.关闭线程池
pool.shutdown();
}
}
class ThreadPoolRunnable implements Runnable{
private int i = 0;
@Override
public void run() {
while(i <= 100){
System.out.println(Thread.currentThread().getName() + " : " + i++);
}
}
}
class ThreadPoolCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int sum =0;
for(int i=1;i<=100;i++){
sum+=i;
}
System.out.println(Thread.currentThread().getName() + " : " +sum);
return sum;
}
}