线程池的好处
- 降低资源的消耗
- 提高响应的速度
- 方便管理
线程复用,可以控制最大并发数,管理线程
线程池:三大方法
Executors
- Executors.newSingleThreadExecutor()
- Executors.newFixedThreadPool(num)
- Executors.newCachedThreadPool()
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo01 {
public static void main(String[] args){
ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程
// ExecutorService threadPool = Executors.newFixedThreadPool(5);//创建一个固定大小的线程池
// ExecutorService threadPool = Executors.newCachedThreadPool();//可伸缩的
try {
for (int i=0;i<10;i++){
//使用线程池创建线程
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
//线程池关闭
threadPool.shutdown();
}
}
}
七大参数
ThreadPoolExecutor中的
- corePoolSize 核心线程池大小
- maximumPoolSize 最大线程池大小
- keepAliveTime 超时无调用就会释放
- TimeUnit unit 超时单位
- BlockingQueue workQueue 阻塞队列
- ThreadFactory threadFactory 线程工厂,创建线程的,一般不用
- RejectedExecutionHandler handler 拒绝策略
public static ExecutorService newSingleThreadExecutor() {
return new Executors.FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());
}
public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
int maximumPoolSize,// 最大线程池大小
long keepAliveTime, //超时无调用就会释放
TimeUnit unit, //超时单位
BlockingQueue<Runnable> workQueue, //阻塞队列
ThreadFactory threadFactory,//线程工厂,创建线程的,一般不用
RejectedExecutionHandler handler//拒绝策略) {
this.ctl = new AtomicInteger(ctlOf(-536870912, 0));
this.mainLock = new ReentrantLock();
this.workers = new HashSet();
this.termination = this.mainLock.newCondition();
if (corePoolSize >= 0 && maximumPoolSize > 0 && maximumPoolSize >= corePoolSize && keepAliveTime >= 0L) {
if (workQueue != null && threadFactory != null && handler != null) {
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
} else {
throw new NullPointerException();
}
} else {
throw new IllegalArgumentException();
}
}
直接使用Executors创建线程池,可能会造成内存溢出,
因为FixedThreadPool和SingleThreadPool允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量请求,导致OOM;
CacheThreadPool和ScheduledThreadPool允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量线程,导致OOM。
建议最好使用ThreadPoolExecutor直接创建线程池
四种拒绝策略
import java.util.concurrent.*;
/**
* ThreadPoolExecutor.AbortPolicy() 超出最大承载后直接抛出异常
* ThreadPoolExecutor.CallerRunsPolicy() 让主线程运行
* ThreadPoolExecutor.DiscardPolicy() 不抛出异常 丢掉任务
* ThreadPoolExecutor.DiscardOldestPolicy() 队列满了尝试和最早进入的线程竞争,如果竞争失败丢弃,不抛异常
*/
public class Demo2 {
public static void main(String[] args){
//手动创建线程池
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
//new ThreadPoolExecutor.AbortPolicy());
//new ThreadPoolExecutor.CallerRunsPolicy());
new ThreadPoolExecutor.DiscardOldestPolicy());
try {
//最大承载 Depue+max
//超出最大承载 AbortPolicy抛出异常
for (int i=1;i<=9;i++){
//使用线程池创建线程
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
//线程池关闭
threadPool.shutdown();
}
}
}
最大线程数如何定义
- CPU密集型
核数
Runtime.getRuntime().availableProcessors() - IO密集型
判断程序中十分耗费IO的线程数量n,设置最大线程数大于n,最好为2n