这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
线程实现的基本知识
继承Thread
- 定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务,因此把run()方法称为执行体
- 创建Thread子类的实例,即创建了线程对象
- 调用线程对象的start()方法来启动该线程。
public class DemoThread extends Thread {
@Override
public void run() {
System.out.println("hello");
}
public static void main(String[] args) {
new DemoThread().start();
}
}
实现Runnable
- 定义Runnable接口的实现类,并重写该接口的run()方法,该run方法的方法体同样是该线程的执行体
- 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象
- 调用线程对象的start()方法来启动该线程
public class DemoThread02 implements Runnable {
@Override
public void run() {
System.out.println("hello");
}
public static void main(String[] args) {
DemoThread02 dt = new DemoThread02();
new Thread(dt, "t1").start();
}
}
实现Callable与Future
- 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
public interface Callable<V> {
V call() throws Exception;
}
-
创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()的返回值。 (FutureTask是一个包装器,它通过接受Callable来创建,它同时实现了Future和Runnable接口)
-
使用FutureTask对象作为Thread对象的target来创建并启动新线程
-
调用FutureTask对象的get()方法获得子线程执行结束后的返回值
public class DemoThread03 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
return 1;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
DemoThread03 dt = new DemoThread03();
FutureTask<Integer> task = new FutureTask<>(dt);
new Thread(task, "有返回值的线程").start();
task.get();
}
}
常用线程池体系结构
- Executor:线程池顶级接口
- ExecutorService:线程池次顶级接口,对Executor做了一些扩展,增加了一些功能
- ScheduledExecutorService:对ExecutorService做了一些扩展,增加一些定时任务相关的功能
- AbstractExecutorService:抽象类,运用模板方法设计模式实现了一部分方法
- ThreadPoolExecutor:普通线程池类,包含一些最基本线程池操作相关的方法实现
- ScheduledThreadPoolExecutor:定时任务线程池类,用于实现定时任务相关功能
- ForkJoinPool:新型线程池类,java7中新增的线程池类,基于工作窃取理论实现,运用于大任务拆小任务,任务无限多的场景
- Executors:线程池工具类,定义了一些快速实现线程池的方法
Executor
抽象出来所有线程的基本执行方法execute(Runnable command)
//线程池顶级接口,定义了一个执行无返回值的方法
public interface Executor {
/**
* 根据Executor的实现判断,可能会在新线程、线程池、线程调用中执行
*/
void execute(Runnable command);
}
ExecutorService
提供了对线程池操作的服务补充
public interface ExecutorService extends Executor {
//关闭线程池,不再接受新的任务,但已提交的任务会执行完成
void shutdown();
/**
* 立即关闭线程池,尝试停止正在运行的任务,未执行的任务将不再执行
* 被迫停止及未执行的任务将以列表的形式返回
*/
List<Runnable> shutdownNow();
//检查线程池是否已关闭
boolean isShutdown();
//检查线程池是否已终止,只有在shutdown()或shutdownNow()之后调用才有可能为true
boolean isTerminated();
//在指定时间内线程池达到终止状态了才会返回true
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
//执行有返回值的任务,任务的返回值为task.call()的结果
<T> Future<T> submit(Callable<T> task);
/**
* 执行有返回值的任务,任务的返回值为这里传入的result
* 当然只有当任务执行完成了调用get()时才会返回
*/
<T> Future<T> submit(Runnable task, T result);
/**
* 执行有返回值的任务,任务的返回值为null
* 当然只有当任务执行完成了调用get()时才会返回
*/
Future<?> submit(Runnable task);
// 批量执行任务,只有当这些任务都完成了这个方法才会返回
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
/**
* 在指定时间内批量执行任务,未执行完成的任务将被取消
* 这里的timeout是所有任务的总时间,不是单个任务的时间
*/
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
//返回任意一个已完成任务的执行结果,未执行完成的任务将被取消(完成一个,把其他的都取消)
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
//在指定时间内如果有任务已完成,则返回任意一个已完成任务的执行结果,未执行完成的任务将被取消
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
ScheduledExecutorService
提供了定时任务的服务补充
public interface ScheduledExecutorService extends ExecutorService {
/**
* 在指定的延时后执行一次
* @param delay 从现在开始到延时执行的时间
*/
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
//在指定的延时后执行一次
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
/**
* 在指定的延时后首先执行一次,随后按照周期执行,不包含任务执行的时间
* @param initialDelay 第一次执行时间
* @param period 两次执行的时间间隔,不包含上一个任务执行时间
* 第一次执行时间:initialDelay
* 第二次执行时间:initialDelay+period
* 第三次执行时间:initialDelay+period*2
*/
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
/**
* 在指定的延时后首先执行一次,随后按照指定延时重复执行,相当于包含任务执行的时间
* @param initialDelay 第一次执行时间
* @param delay 一个任务执行结束到另一个任务开始执行之间的延迟,延时以上一个任务结束开始计算
*/
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
}
ThreadPoolExecutor解析
ThreadPoolExecutor的5种状态
- RUNNING:接收新任务和进程队列任务
- SHUTDOWN:不接收新任务,但是接收进程队列任务
- STOP:不接收新任务也不接收进程队列任务,并且打断正在进行中的任务
- TIDYING:所有任务终止,待处理任务数量为0,线程转换为TIDYING,将会执行terminated钩子函数
- TERMINATED:terminated()执行完成
状态之间的转换:
- RUNNING -> SHUTDOWN:调用shutdown()方法
- (RUNNING or SHUTDOWN)-> STOP:调用shutdownNow()方法
- SHUTDOWN -> TIDYING:队列和线程池都是空的
- STOP -> TIDYING:线程池为空
- TIDYING -> TERMINATED:钩子函数terminated()执行完成
4种丢弃策略:
- CallerRunsPolicy:调用execute()的线程中运行被拒绝的任务【背压】
- AbortPolicy:抛RejectedExecutionException异常(默认的处理方式)
- DiscardPolicy:悄悄丢弃拒绝的任务
- DiscardOldestPolicy:丢弃最老的未处理任务,然后重新执行execute()方法
源码分析:
- 向ThreadPool提交任务-execute()
- 创建新线程-addWorker(Runnable firstTask, boolean core)
- 线程的主循环Worker.runWorker(Worker w)
- 从队列中获取排队的任务-getTask()
- 线程结束-processWorkerExit(Worker w, boolean completedAbruptly)
- shutdown()、shutdownNow()、tryTerminate()
ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor继承自ThreadPoolExecutor,主要用来在给定的延迟之后运行任务,或者定期执行任务:
- 使用自定义任务类型ScheduledFutureTask,即使不需要调度的任务也会被认为是延时为0的延时任务
- 使用自定义的队列DelayedWorkQueue,DelayQueue是无界队列,与ThreadPoolExecutor比较缺少容量的限制、corePoolSize、maximumPoolSize,有效的简化了一些执行机制
任务队列DelayedWorkQueue
DelayedWorkQueue基于堆的数据结构(小顶堆),ScheduledFutureTask将索引记录在堆数组。
static class DelayedWorkQueue extends AbstractQueue<Runnable>
implements BlockingQueue<Runnable> {
//初始化数组大小
private static final int INITIAL_CAPACITY = 16;
//存储任务的数组
private RunnableScheduledFuture<?>[] queue =
new RunnableScheduledFuture<?>[INITIAL_CAPACITY];
//线程安全锁
private final ReentrantLock lock = new ReentrantLock();
//元素数量
private int size = 0;
//领导线程
private Thread leader = null;
//和lock对应的Condition用于线程的等待和唤醒
private final Condition available = lock.newCondition();
}
主要方法分析:
- 元素的添加操作--offer()
- 调整数组大小--grow()
- 元素的取出操作--take()
- finishPoll()、remove()、siftUp()、siftDown()、poll()
任务对象ScheduledFutureTask
private class ScheduledFutureTask<V>
extends FutureTask<V> implements RunnableScheduledFuture<V> {
//任务序列号
private final long sequenceNumber;
//任务执行的时间单位是毫秒
private long time;
/**
* 重复执行任务的周期
* 正数表示固定周期执行
* 负数表示固定延时执行
* 0表示不是周期任务
*/
private final long period;
//this的包装任务,用于周期任务的提交
RunnableScheduledFuture<V> outerTask = this;
//延时队列的索引号
int heapIndex;
}
主要方法分析:
- 任务对象大小比较--compareTo(Delayed other)
- run()、取消任务--cancel()