线程实现方式
Thread、Runnable、Callable
//实现Runnable接口的类将被Thread执行,表示一个基本任务
public interface Runnable {
//run方法就是它所有内容,就是实际执行的任务
public abstract void run();
}
//Callable同样是任务,与Runnable接口的区别在于它接口泛型,同时它执行任务候带有返回值;
//Callable的使用通过外层封装成Future来使用
public interface Callable<V> {
//相对于run方法,call方法带有返回值
V call() throws Exception;
}
注意:启动Thread线程只能用start(JNI方法)来启动,start方法通知虚拟机,虚拟机通过调用器映射到底层操作系统,通过操作系统来创建线程来执行当前任务的run方法
Executor框架
Executor接口是线程池框架中最基础的部分,定义了一个用于执行Runnable的execute方法。从图中可以看出Exectuor下有一个重要的子接口ExecutorService,其中定义了线程池的具体行为:
-
execute(Runnable runnable):执行Runnable类型的任务
-
submit(task):用来提交Callable或者Runnable任务,并返回代表此任务的Future对象
-
shutdown():在完成已经提交的任务后封闭办事,不在接管新的任务
-
shutdownNow():停止所有正在履行的任务并封闭办事
-
isTerminated():是一个钩子函数,测试是否所有任务都履行完毕了
-
isShutdown():是一个钩子函数,测试是否该ExecutorService是否被关闭
ExecutorService中的重点属性:
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
ctl:对线程池的运行状态和线程池中有效线程的数量进行控制的一个字段,它包含两部分信息:线程池的运行状态(runState)和线程池内有效线程的数量(workerCount)。
这里可以看到,使用Integer类型来保存,高3位保存runState,低29位保存workerCount。COUNT_BITS 就是29,CAPACITY 就是1左移29位减1(29个1),这个常量表示workerCount的上限值,大约是5亿。
ctl相关方法:
//获取运行状态
private static int runStateOf(int c){
return c & ~CAPACITY;
}
//获取活动线程数
private static int workerCountOf(int c) {
return c & CAPACITY;
}
//获取运行状态和活动线程数的值
private static int ctlOf(int rs, int wc) {
return rs | wc;
}
线程池的状态:
RUNNING = -1 << COUNT_BITS; //高3位为111
SHUTDOWN = 0 << COUNT_BITS; //高3位为000
STOP = 1 << COUNT_BITS; //高3位为001
TIDYING = 2 << COUNT_BITS; //高3位为010
TERMINATED = 3 << COUNT_BITS; //高3位为011
线程池实例的状态
1、RUNNING
- 状态说明:线程池处于RUNNING状态,能够接收新任务,以及对已添加的任务进行处理。
- 状态切换:线程池的初始化状态是RUNNING。换句话说,线程池一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0。
2、SHUTDOWN
- 状态说明:线程池处于SHUTDOWN状态,不接收新任务,能够处理已经添加的任务。
- 状态切换:调用shutdown()方法时,线程池由RUNNING -> SHUTDOWN。
3、STOP
- 状态说明:线程池处于STOP状态,不接收新任务,不处理已提交的任务,并且会中断正在处理的任务。
- 状态切换:调用线程池中的shutdownNow()方法时,线程池由(RUNNING or SHUTDOWN) -> STOP。
4、TIDYING
- 状态说明:当所有的任务已经停止,ctl记录“任务数量”为0,线程池会变为TIDYING状态。当线程池处于TIDYING状态时,会执行钩子函数 terminated()。terminated()在ThreadPoolExecutor类中是空, 的,若用户想在线程池变为TIDYING时,进行相应处理,可以通过重载 terminated()函数来实现。
- 状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行任务也为空时,就会由SHUTDOWN -> TIDYING。当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP-> TIDYING。
5、TERMINATED
- 状态说明:线程池线程池彻底停止,线程池处于TERMINATED状态,
- 状态切换:线程池处于TIDYING状态时,执行完terminated()之后, 就会由TIDYING->TERMINATED。
线程池使用
ThreadPoolExecutor构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
任务的提交流程
执行图:
网友评论