Java 线程池
一:初识
1)构造方法
public ThreadPoolExecutor(int corePoolSize,//核心线程数量
int maximumPoolSize,//最大连接数
long keepAliveTime,//最大空闲时间
TimeUnit unit,//时间单位
BlockingQueue<Runnable> workQueue,//任务队列
ThreadFactory threadFactory,//线程工厂
RejectedExecutionHandler handler//饱和处理机制
){
}
2)逻辑顺序
3)参数设计
- 核心线程数的设计需要根据任务处理时间和每秒产生的任务数量确定,尽可能满足8020原则
- 任务队列长度的设计一般为:核心线程数/单个任务执行时间*2
- 最大线程数的设计一般为:(最大任务数-任务队列长度)*单个任务执行时间
- 最大空闲时间与设备有关,可以根据经验设定
上面四个参数的设计只是一般设计原则,并不是固定的,可以根据实际情况进行调整
二:自定义线程池
package com.harlon.demo1;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class MyThreadPool {
//任务队列
private List<Runnable> tasks = Collections.synchronizedList(new LinkedList<>());
//当前线程数量
private int num;
//核心线程数量
private int corePoolSize;
//最大线程数量
private int maxSize;
//任务队列长度
private int workSize;
public MyThreadPool(int corePoolSize, int maxSize, int workSize) {
this.corePoolSize = corePoolSize;
this.maxSize = maxSize;
this.workSize = workSize;
}
//提交任务
public void submit(Runnable r){
if (tasks.size() >= workSize){
System.out.println("任务 "+r+" 被丢弃了");
}else {
tasks.add(r);
execTask(r);
}
}
//用于执行任务
private void execTask(Runnable r) {
if (num < corePoolSize){
new MyWorker(" 核心线程:"+num,tasks).start();
num++;
}else if (num <maxSize){
new MyWorker("非核心线程:"+num,tasks).start();
num++;
}else {
System.out.println("任务:"+r+"被缓存了");
}
}
}
三:内置线程池
1)种类
1. newSingleThreadExecutor
创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
2.newFixedThreadPool
创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
3. newCachedThreadPool
创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,
那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
4.newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行
注意:ScheduledThreadPool的下的方法(获取均通过 Excutors 的静态方法)
/**
* 带延迟时间的调度,只执行一次
* 调度之后可通过Future.get()阻塞直至任务执行完毕
*/
1. public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
/**
* 带延迟时间的调度,只执行一次
* 调度之后可通过Future.get()阻塞直至任务执行完毕,并且可以获取执行结果
*/
2. public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
/**
* 带延迟时间的调度,循环执行,固定频率
*/
3. public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
/**
* 带延迟时间的调度,循环执行,固定延迟
*/
4. public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
2)常用方法
1.ExecutorServices
方法名 | 作用 |
---|---|
isShutDown() | 如果此执行程序已关闭,则返回 true。 |
isTerminated() | 如果关闭后所有任务都已完成,则返回 true。 |
shutdown() | 启动一次顺序关闭,执行以前提交的任务,但不接受新任务。 |
shutdownNow() | 试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。 |
submit(task) | 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future。 |
3)异步计算结果
方法名 | 作用 |
---|---|
boolean cancel (boolean mayInterruptIfRunning) | 取消任务的执行。参数指定是否立即中断任务执行,或者等等任务结束 |
boolean isCancelled () | 任务是否已经取消,任务正常完成前将其取消,则返回 true |
boolean isDone () | 需要注意的是如果任务正常终止、异常或取消,都将返回true |
V get () throws InterruptedException, ExecutionException | 等待任务执行结束,然后获得V类型的结果。InterruptedException 线程被中断异常, ExecutionException任务执行异常,如果任务被取消,还会抛出CancellationException |
V get (long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException | 同上面的get功能一样,多了设置超时时间。参数timeout指定超时时间,uint指定时间的单位,在枚举类TimeUnit中有相关的定义。如果计算超时,将抛出TimeoutException |