线程是调度CPU资源的最小单位,线程模型分为KLT模型与ULT模型,JVM使用的是KLT模型,java线程与OS线程保持1:1的映射关系,也就是说有一个java线程也会在操作系统里有一个对应的线程。
Java线程的生命状态:
NEW 新建
RUNNABLE 运行
BLOCKED 阻塞
WAITING 等待
TIMED_WAITING 超时等待
TERMINATED 终结
线程池
什么时候使用线程池?
1. 单个任务处理时间比较短
2. 需要处理的任务数量很大
线程池优势:
1. 重用存在的线程,减少线程创建,消亡的开销,提高性能
2. 提高响应速度,当任务到达时,任务可以不需要等到线程创建就能立即执行。
3. 提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
```
int corePoolSize, 核心线程数
int maximumPoolSize, 最大线程数
long keepAliveTime, 最大允许线程不干活的时间
TimeUnit unit, 时间单位
BlockingQueue<Runnable> workQueue, 存放未来得及执行的任务
ThreadFactory threadFactory, 创建线程的工厂
RejectedExecutionHandler handler 拒绝策略
```
执行流程:
1. 当核心线程数还未满时,此时有个新的任务过来,即使存在空闲的线程,也不会让其执行,还是会新建线程来执行该任务
2. 当核心线程数满了,此时新的任务会往队列中存放,
3. 当队列中满了,此时会新建非核心线程来处理任务
4. 当非核心线程也满了,此时再有新的任务过来,则会执行拒绝策略
注意点:
非核心线程创建并执行完当前任务后,是会继续执行队列中的任务还是直接销毁?
1. 核心线程和非核心线程,都是线程
2. 当新建了线程,线程首先执行任务;执行完成之后会从workQueue队列中取任务。队列可能为空,因此线程取任务可能会阻塞。在从队列获取任务前,线程池会先进行判断,当线程数量>coreSize时,说明可以消减线程了,就会给该线程设置从队列取任务的最长阻塞时间(keepAliveTime),超时返回null,即表示该线程空闲了keepAliveTime时间,并且线程池数大于corePoolSize核心线程数,就会将该线程销毁。
原文链接:https://blog.csdn.net/qq_41257358/article/details/122202547
线程池的状态:
1. RUNNING -1
状态说明:线程池的初始状态,接收新的任务且处理队列中的任务
2. SHUTDOWN 0
状态说明:不接收新的任务,但处理队列中的任务
状态切换:调用线程池的shutdown()接口时,线程池由RUNNING->SHUTDOWN
3. STOP 1
状态说明:既不接收新的任务,也不处理队列中的任务,并且会中断正在处理的任务
状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN)->STOP
4. TIDYING 2
状态说明:当所有的任务已终止,ctl记录的任务数量为0,线程池会变为TIDYING状态.此时会执行钩子函数terminated(),terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理,可以通过重载terminated()函数来实现
状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空,且线程池中执行的任务也为空时,就会由SHUTDOWN->TIDYING.当线程在STOP状态下,线程池中执行的任务为空时,就会由STOP->TIDYING
5. TERMINATED 3
状态说明:线程池彻底终止,就变成了TERMINATED状态
状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由TIDYING->TERMINATED.
进入TERMINATED的条件如下:
5.1 线程池不是RUNNING状态
5.2 线程池状态不是TIDYING或TERMINATED状态
5.3 如果线程池状态是SHUTDOWN并且workerQueue为空
5.4 workCount为0
5.5 设置TIDYING状态成功
拒绝策略
当非核心线程都处理不了任务时,则执行拒绝策略
AbortPolicy:默认执行策略,直接往外抛异常
CallerRunsPolicy:如果线程池没有关闭,则由当前线程自己执行该任务
DiscardPolicy:不处理当前任务,即丢弃当前任务
DiscardOldestPolicy:丢弃最老的任务,将新任务放入队列
ThreadPoolExecutor.runWorker :循环获取任务,这也是为什么线程能重用的原因
```
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
// 循环,判断任务是否还有未执行的,获取到则执行
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
```
getTask(),
```
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
// Are workers subject to culling?
//allowCoreThreadTimeOut 允许核心线程超时:默认是false,可以手动设置为true,线程小于corePoolSize数,则为false
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
Runnable r = timed ?
// 阻塞队列,当队列为空,则阻塞,阻塞时间keepAliveTime,
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
// 没有时间限制,核心线程就可以一直等待,当队列中新增任务后,就会唤醒线程
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
```
获取不到任务后,就执行该方法processWorkerExit
```
private void processWorkerExit(Worker w, boolean completedAbruptly) {
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount();
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
completedTaskCount += w.completedTasks;
// 移除线程
workers.remove(w);
} finally {
mainLock.unlock();
}
tryTerminate();
int c = ctl.get();
// 判断当前的线程池的状态是否为RUNNING或shutdown
if (runStateLessThan(c, STOP)) {
if (!completedAbruptly) {
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
if (min == 0 && ! workQueue.isEmpty())
min = 1;
if (workerCountOf(c) >= min)
return; // replacement not needed
}
// 新增非核心线程
addWorker(null, false);
}
}
```
线程数量设置:
CPU密集型:cpu核数+1,CPU密集型也叫计算密集型,指的是系统的硬盘、内存性能相对CPU要好很多,此时,系统运作CPU读写IO(硬盘/内存)时,IO可以在很短的时间内完成,而CPU还有许多运算要处理,因此,CPU负载很高。
IO密集型:2cpu核数+1,IO密集型指的是系统的CPU性能相对硬盘、内存要好很多,此时,系统运作,大部分的状况是CPU在等IO (硬盘/内存) 的读写操作,因此,CPU负载并不高。
标签:状态,队列,任务,线程,null,CPU From: https://www.cnblogs.com/wanthune1/p/17241948.html