一.使用线程池的好处
1.提高系统性能和响应速度:线程池可以通过复用线程来减少线程的创建和销毁,从而减少了系统开销,提高了系统的性能和响应速度。
2.提高代码的可维护性:使用线程池可以将任务的执行与线程的创建和管理分离开来,使得代码更加清晰易懂,也更加容易维护。
3.提高代码的可复用性:线程池可以让不同的任务共享同一个线程池,从而提高代码的可复用性。
二.ThreadPoolExecutor线程池的参数解释
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
1.corePoolSize:核心线程池大小,即线程池中保留的线程数,即使它们处于空闲状态。如果新的任务提交给线程池时,核心线程池中的线程都在忙碌状态,那么新任务就会被添加到工作队列中等待执行。
2.maximumPoolSize:最大线程池大小,即线程池中最多可以创建的线程数。如果工作队列已满并且线程池中的线程数小于最大线程池大小,则会创建新的线程来执行任务。
3.keepAliveTime:空闲线程存活时间,即当一个线程处于空闲状态时,它最多可以存活多长时间。如果线程池中的线程数超过了核心线程池大小,空闲的线程将会被回收,直到线程池中的线程数等于核心线程池大小为止。
4.unit:keepAliveTime的时间单位。
5.workQueue:任务队列,用于存储等待执行的任务。当所有的核心线程都在执行任务时,新的任务会被添加到任务队列中等待执行。任务队列有多种实现方式,例如ArrayBlockingQueue、LinkedBlockingQueue等。
三.线程池的执行流程(execute方法)
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
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);
1.当有任务需要执行时,首先判断当前线程池中的线程数是否小于核心线程数,如果是,则创建一个新的核心线程来执行任务。
2.如果当前线程池中的线程数已经达到核心线程数,则将任务放入任务队列中等待执行。
3.当任务队列已满时,如果当前线程池中的线程数还没有达到最大线程数,则创建新的非核心线程来执行任务。
4.如果当前线程池中的线程数已经达到最大线程数,则采取拒绝策略,例如抛出异常或者执行一些默认操作。
四.addWorker方法
1.参数解释
addWorker方法有两个参数,第一个参数表示要加入的线程,第二个参数表示该线程是否为核心线程。
2.执行流程
(1)获取线程池的状态,并检查线程池是否处于关闭状态。如果线程池已经关闭,且队列中还有任务等待执行,就不会再添加新的工作线程。如果线程池已经关闭,且队列中没有任务等待执行,也不会再添加新的工作线程。
(2)检查线程池中的工作线程数量是否已经达到了最大值,以及是否已经达到了核心线程数或最大线程数。如果工作线程数量已经达到了限制,就不会再添加新的工作线程。
(3)如果可以添加新的工作线程,方法会创建一个新的Worker对象,并将其添加到线程池中。如果添加成功,线程池会启动这个新的工作线程。