当前位置: 首页 > news >正文

宜春做网站哪里好网站建设企业网站制作

宜春做网站哪里好,网站建设企业网站制作,火车头采集器wordpress3发布模块,中国建设银行网站的社保板块在哪里目录 1.Java 的线程池 2.Tomcat 的线程池 学习Tomcat的时候#xff0c;有很多绚丽的技术值得我们学习#xff0c;但是个人认为Tomcat的线程池扩展是最值得研究的一个部分#xff0c;线程池的应用太广了#xff0c;也重要了#xff0c;Java原生线程池的特征我相信很多人都…目录 1.Java 的线程池 2.Tomcat 的线程池 学习Tomcat的时候有很多绚丽的技术值得我们学习但是个人认为Tomcat的线程池扩展是最值得研究的一个部分线程池的应用太广了也重要了Java原生线程池的特征我相信很多人都背过那Tomcat为什么要扩展以及如何拓展的呢这个问题理解了面试的时候就可以提升一下逼格。 在开发中我们经常会碰到“池”的概念比如数据库连接池、内存池、线程池、常量池等。为什么需要“池”呢程序运行的本质就是通过使用系统资源CPU、内存、网络、磁盘等来完成信息的处理比如在 JVM 中创建一个对象实例需要消耗 CPU 和内存资源如果你的程序需要频繁创建大量的对象并且这些对象的存活时间短就意味着需要进行频繁销毁那么很有可能这部分代码会成为性能的瓶颈。 而“池”就是用来解决这个问题的简单来说对象池就是把用过的对象保存起来等下一次需要这种对象的时候直接从对象池中拿出来重复使用避免频繁地创建和销毁。在 Java 中万物皆对象线程也是一个对象Java 线程是对操作系统线程的封装创建 Java 线程也需要消耗系统资源因此就有了线程池。JDK 中提供了线程池的默认实现我们也可以通过扩展 Java 原生线程池来实现自己的线程池。 同样为了提高处理能力和并发度Web 容器一般会把处理请求的工作放到线程池里来执行Tomcat 扩展了原生的 Java 线程池来满足 Web 容器高并发的需求下面我们就来学习一下 Java 线程池的原理以及 Tomcat 是如何扩展 Java 线程池的。 1.Java 的线程池 简单的说Java 线程池里内部维护一个线程数组和一个任务队列当任务处理不过来的时就把任务放到队列里慢慢处理。 ThreadPoolExecutor 我们先来看看 Java 线程池核心类 ThreadPoolExecutor 的构造函数你需要知道 ThreadPoolExecutor 是如何使用这些参数的这是理解 Java 线程工作原理的关键。 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueueRunnable workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)不要小看这几个参数其完整的工作过程如下 每次提交任务时如果线程数还没达到核心线程数corePoolSize线程池就创建新线程来执行。当线程数达到corePoolSize后新增的任务就放到工作队列workQueue里而线程池中的线程则努力地从workQueue里拉活来干也就是调用 poll 方法来获取任务。 如果任务很多并且workQueue是个有界队列队列可能会满此时线程池就会紧急创建新的临时线程来救场如果总的线程数达到了最大线程数maximumPoolSize则不能再创建新的临时线程了转而执行拒绝策略handler比如抛出异常或者由调用者线程来执行任务等。 如果高峰过去了线程池比较闲了怎么办临时线程使用 pollkeepAliveTime, unit方法从工作队列中拉活干请注意 poll 方法设置了超时时间如果超时了仍然两手空空没拉到活表明它太闲了这个线程会被销毁回收。 那还有一个参数threadFactory是用来做什么的呢通过它你可以扩展原生的线程工厂比如给创建出来的线程取个有意义的名字。 FixedThreadPool/CachedThreadPool Java 提供了一些默认的线程池实现比如 FixedThreadPool 和 CachedThreadPool它们的本质就是给 ThreadPoolExecutor 设置了不同的参数是定制版的 ThreadPoolExecutor。 public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueueRunnable()); }public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueueRunnable()); } 从上面的代码你可以看到 FixedThreadPool 有固定长度nThreads的线程数组忙不过来时会把任务放到无限长的队列里这是因为LinkedBlockingQueue 默认是一个无界队列。CachedThreadPool 的 maximumPoolSize 参数值是Integer.MAX_VALUE因此它对线程个数不做限制忙不过来时无限创建临时线程闲下来时再回收。它的任务队列是SynchronousQueue表明队列长度为 0。 2.Tomcat 的线程池 跟 FixedThreadPool/CachedThreadPool 一样Tomcat 的线程池也是一个定制版的 ThreadPoolExecutor。 通过比较 FixedThreadPool 和 CachedThreadPool我们发现它们传给 ThreadPoolExecutor 的参数有两个关键点 是否限制线程个数。是否限制队列长度。 对于 Tomcat 来说这两个资源都需要限制也就是说要对高并发进行控制否则 CPU 和内存有资源耗尽的风险。因此 Tomcat 传入的参数是这样的 // 定制版的任务队列 taskqueue new TaskQueue(maxQueueSize);// 定制版的线程工厂 TaskThreadFactory tf new TaskThreadFactory(namePrefix,daemon,getThreadPriority());// 定制版的线程池 executor new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), maxIdleTime, TimeUnit.MILLISECONDS,taskqueue, tf); 你可以看到其中的两个关键点 Tomcat 有自己的定制版任务队列和线程工厂并且可以限制任务队列的长度它的最大长度是 maxQueueSize。Tomcat 对线程数也有限制设置了核心线程数minSpareThreads和最大线程池数maxThreads。 除了资源限制以外Tomcat 线程池还定制自己的任务处理流程。我们知道 Java 原生线程池的任务处理逻辑比较简单 前 corePoolSize 个任务时来一个任务就创建一个新线程。后面再来任务就把任务添加到任务队列里让所有的线程去抢如果队列满了就创建临时线程。如果总线程数达到 maximumPoolSize执行拒绝策略。 Tomcat 线程池扩展了原生的 ThreadPoolExecutor通过重写 execute 方法实现了自己的任务处理逻辑 前 corePoolSize 个任务时来一个任务就创建一个新线程。再来任务的话就把任务添加到任务队列里让所有的线程去抢如果队列满了就创建临时线程。如果总线程数达到 maximumPoolSize则继续尝试把任务添加到任务队列中去。如果缓冲队列也满了插入失败执行拒绝策略。 观察 Tomcat 线程池和 Java 原生线程池的区别其实就是在第 3 步Tomcat 在线程总数达到最大数时不是立即执行拒绝策略而是再尝试向任务队列添加任务添加失败后再执行拒绝策略。那具体如何实现呢其实很简单我们来看一下 Tomcat 线程池的 execute 方法的核心代码。 public class ThreadPoolExecutor extends java.util.concurrent.ThreadPoolExecutor {...public void execute(Runnable command, long timeout, TimeUnit unit) {submittedCount.incrementAndGet();try {// 调用 Java 原生线程池的 execute 去执行任务super.execute(command);} catch (RejectedExecutionException rx) {// 如果总线程数达到 maximumPoolSizeJava 原生线程池执行拒绝策略if (super.getQueue() instanceof TaskQueue) {final TaskQueue queue (TaskQueue)super.getQueue();try {// 继续尝试把任务放到任务队列中去if (!queue.force(command, timeout, unit)) {submittedCount.decrementAndGet();// 如果缓冲队列也满了插入失败执行拒绝策略。throw new RejectedExecutionException(...);}} }} } 从这个方法你可以看到Tomcat 线程池的 execute 方法会调用 Java 原生线程池的 execute 去执行任务如果总线程数达到 maximumPoolSizeJava 原生线程池的 execute 方法会抛出 RejectedExecutionException 异常但是这个异常会被 Tomcat 线程池的 execute 方法捕获到并继续尝试把这个任务放到任务队列中去如果任务队列也满了再执行拒绝策略。 定制版的任务队列 细心的你有没有发现在 Tomcat 线程池的 execute 方法最开始有这么一行 submittedCount.incrementAndGet();这行代码的意思把 submittedCount 这个原子变量加一并且在任务执行失败抛出拒绝异常时将这个原子变量减一 submittedCount.decrementAndGet();其实 Tomcat 线程池是用这个变量 submittedCount 来维护已经提交到了线程池但是还没有执行完的任务个数。Tomcat 为什么要维护这个变量呢这跟 Tomcat 的定制版的任务队列有关。Tomcat 的任务队列 TaskQueue 扩展了 Java 中的 LinkedBlockingQueue我们知道 LinkedBlockingQueue 默认情况下长度是没有限制的除非给它一个 capacity。因此 Tomcat 给了它一个 capacityTaskQueue 的构造函数中有个整型的参数 capacityTaskQueue 将 capacity 传给父类 LinkedBlockingQueue 的构造函数。 public class TaskQueue extends LinkedBlockingQueueRunnable {public TaskQueue(int capacity) {super(capacity);}... } 这个 capacity 参数是通过 Tomcat 的 maxQueueSize 参数来设置的但问题是默认情况下 maxQueueSize 的值是Integer.MAX_VALUE等于没有限制这样就带来一个问题当前线程数达到核心线程数之后再来任务的话线程池会把任务添加到任务队列并且总是会成功这样永远不会有机会创建新线程了。 为了解决这个问题TaskQueue 重写了 LinkedBlockingQueue 的 offer 方法在合适的时机返回 false返回 false 表示任务添加失败这时线程池会创建新的线程。那什么是合适的时机呢请看下面 offer 方法的核心源码 public class TaskQueue extends LinkedBlockingQueueRunnable {...Override// 线程池调用任务队列的方法时当前线程数肯定已经大于核心线程数了public boolean offer(Runnable o) {// 如果线程数已经到了最大值不能创建新线程了只能把任务添加到任务队列。if (parent.getPoolSize() parent.getMaximumPoolSize()) return super.offer(o);// 执行到这里表明当前线程数大于核心线程数并且小于最大线程数。// 表明是可以创建新线程的那到底要不要创建呢分两种情况//1. 如果已提交的任务数小于当前线程数表示还有空闲线程无需创建新线程if (parent.getSubmittedCount()(parent.getPoolSize())) return super.offer(o);//2. 如果已提交的任务数大于当前线程数线程不够用了返回 false 去创建新线程if (parent.getPoolSize()parent.getMaximumPoolSize()) return false;// 默认情况下总是把任务添加到任务队列return super.offer(o);}} 从上面的代码我们看到只有当前线程数大于核心线程数、小于最大线程数并且已提交的任务个数大于当前线程数时也就是说线程不够用了但是线程数又没达到极限才会去创建新的线程。这就是为什么 Tomcat 需要维护已提交任务数这个变量它的目的就是在任务队列的长度无限制的情况下让线程池有机会创建新的线程。 当然默认情况下 Tomcat 的任务队列是没有限制的你可以通过设置 maxQueueSize 参数来限制任务队列的长度。 参考 本文很多内容参考了李号双老师的相关文章
http://www.zqtcl.cn/news/1016/

相关文章:

  • 国基建设集团有限公司网站沈阳百度首页优化
  • 郴州网站建设ku0735社交app开发成本预算表
  • 做poster的网站wordpress 每页文章数量
  • 网站域名怎么快速备案价格wordpress代码增强插件
  • 企业自己建网站怎么建iis8.5 wordpress
  • 温州网站建设的公司一个网站2级域名多
  • 网站一般做多大的wordpress搜索安全
  • seo描述快速排名seo关键词排名优化销售
  • 创业项目的网站做网站数据库设计
  • 给网站设置关键词在网站建设中要注意的问题
  • 大型门户网站系统合肥做网站便宜
  • 互联网官方网站医疗公司logo设计图片
  • 做网站用什么编程软件一网网站制作平台
  • wordpress 2.0漏洞手机网站 搜索优化 百度
  • 做网站不花钱新平台推广文案
  • 什么手机可做网站做网站找什么公司
  • 门户网站建设请示家装设计需要学什么软件
  • 国内规模大的建站公司连接wordpress
  • 珠海网站制作软件网站seo做点提升流量
  • 佛山市做网站的ui设计工具有哪些
  • 建设网站中期要做什么长春企业建站平台
  • 沂水做网站北京购物网站建设公司
  • 网站建设费会计分录网络公司的网页设计
  • 睢县网站建设云服务器网站搭建教程
  • html5做网站链接范例网站开发成本预算
  • 扁平化的网站有哪些中国零售业博览会
  • 淮南公司网站建设多少费用怀化职院网站
  • 邓州市建设局网站佛山网站建设哪家专业
  • 微信公众号对接网站建设网站需要几个文件夹
  • 网站技术培训学校网站如何在360做提交