线程使用上的常见问题
- new Thread().start()
- 线程的繁忙创建和销毁
- 线程的数据过多,会导致CPU资源的上下文切换开销问题
java中提供的四种常见的线程池
- newFixedThreadPool :固定线程数量
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
- newSingleThreadExecutor :只有一个线程的线程池
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
- newCachedThreadPool :可缓存的线程池 -> 理论上说有多少个请求就可以创建多少个线程来处理
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
- newScheduledThreadPool :提供指定周期执行的线程池
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
实现线程复用原理拆解
- 实现线程重复使用的唯一方法就是让线程一直运行中
- 线程一直运行中如何获取新的任务呢,【可以使用共享队列AQS,让所有线程从里面获取任务】
- 考虑到如果没有任务的时候让线程停止,避免浪费cpu。有任务唤醒,没有任务着阻塞,类似一个生产者和消费者关系【可以使用LinkedBlockingQueue,获取任务】
- 拒绝策略:在队列已满的情况下如何处理
ExecutorService.execute() 底层原理
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get(); // 获取当前线程池创建线程
if (workerCountOf(c) < corePoolSize) { // 判断是否创建完所有核心线程
if (addWorker(command, true)) // 添加工作线程,并执行任务
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) { // workQueue.offer 添加到阻塞队列当中
int recheck = ctl.get(); // 如果阻塞队列满了,获取当前线程池中线程数量
if (! isRunning(recheck) && remove(command)) // 等待队列当中清除任务
reject(command); //拒绝策略
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false)) // 队列已满,最大线程数扩容数量
reject(command); // //拒绝策略
}
// 将任务添加到等待队列当中
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// 检查队列是否为空,或任务为空
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize)) // 判断当前线程数量是否已满
return false;
if (compareAndIncrementWorkerCount(c)) // 通过cas修改线程池核心数
break retry; // 修改成功跳出当前循环
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// 否则CAS由于workerCount更改而失败;重试内循环
}
}
//初始化工作线程
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
w = new Worker(firstTask); // 创建线程
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // 检查是否可以启动当前线程线程
throw new IllegalThreadStateException();
workers.add(w); // 将当前线程添加set线程队列当中
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s; // 重新更新largestPoolSize
workerAdded = true; //添加成功
}
} finally {
mainLock.unlock();
}
if (workerAdded) { // 添加成功并启动线程
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted) // 添加失败,回滚
addWorkerFailed(w);
}
return workerStarted;
}
线程run方法
// 线程启动后执行的任务run方法
public void run() {
runWorker(this);
}
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();
// 如果pool正在停止,确保线程被中断
// 如果不是,确保线程不被中断。
// 这需要在第二种情况下重新检查处理shutdownNow在清除中断时运行
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);
}
}
// 在任务等待队列种获取任务,如果在指定时间未获取任务着释放当前无用线程
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?
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ((wc > maximumPoolSize || (timed && timedOut)) // 如果当前线程数过大,或者长时间未使用,队列为空,着释放当前线程
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
// 在AQS任务队列人拿任务,如果未拿到任务着阻塞等待
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}