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

长春火车站到龙嘉机场高铁时刻表网站建设规划公司地址

长春火车站到龙嘉机场高铁时刻表,网站建设规划公司地址,如何建立自己的摄影网站,淘宝 wordpress文章内容已经收录在《面试进阶之路》#xff0c;从原理出发#xff0c;直击面试难点#xff0c;实现更高维度的降维打击#xff01; 目录 文章目录 目录Java线程池的核心内容详解线程池的优势什么场景下要用到线程池呢#xff1f;线程池中重要的参数【掌握】新加入一个任…文章内容已经收录在《面试进阶之路》从原理出发直击面试难点实现更高维度的降维打击 目录 文章目录 目录Java线程池的核心内容详解线程池的优势什么场景下要用到线程池呢线程池中重要的参数【掌握】新加入一个任务线程池如何进行处理呢【掌握】如何将任务提交到线程池中呢线程池是如何关闭的呢线程池为什么设计为任务队列满了才创建新线程线程池中线程异常后该线程会销毁吗 关于线程池在生产环境中的使用一个项目使用一个线程池还是多个线程池线程池在 RocketMQ 中的使用关于线程数量的设置美团技术团队针对线程池所做的优化自定义拒绝策略阿里手册中的线程池规范 Java线程池的核心内容详解 线程池的优势 首先线程池是将多个线程进行池化操作统一进行管理这样做有什么好处呢 降低创建、销毁线程的开销 线程池中维护固定数量的线程不需要临时进行线程的创建和销毁提高响应速度 对于新提交到线程池中的任务直接使用线程池中的空闲线程可以直接进行处理不需要等待创建线程节省资源可以重复利用线程 什么场景下要用到线程池呢 一般就是多 IO 的场景下需要用到像 IO 任务很多比如数据库操作、请求其他接口操作这都属于 IO 类任务IO 类任务的特点就是只需要线程去启动一下 IO 任务之后就等待 IO 结果返回即可IO 结果返回的时间是比较慢的 因此如果只使用单线程去执行 IO 任务的话由于这个等待时间比较长那么线程需要一直等待 IO 结果返回而无法执行其他操作 因此在多 IO 场景下可以使用线程池来加快 IO 任务的执行开启多个线程同时去启动多个 IO 任务可以加快 IO 任务的处理速度 线程池中重要的参数【掌握】 线程池中重要的参数如下 corePoolSize 核心线程数量maximumPoolSize 线程池最大线程数量 核心线程数非核心线程数keepAliveTime 非核心线程存活时间unit空闲线程存活时间单位keepAliveTime单位workQueue 工作队列任务队列存放等待执行的任务 LinkedBlockingQueue无界的阻塞队列最大长度为 Integer.MAX_VALUEArrayBlockingQueue基于数组的有界阻塞队列按FIFO排序SynchronousQueue同步队列不存储元素对于提交的任务如果有空闲线程则使用空闲线程来处理否则新建一个线程来处理任务PriorityBlockingQueue具有优先级的无界阻塞队列优先级通过参数Comparator实现。 threadFactory 线程工厂创建一个新线程时使用的工厂可以用来设定线程名、是否为daemon线程等等。handler 拒绝策略 有4种 AbortPolicy 直接抛出异常默认策略CallerRunsPolicy用调用者所在的线程来执行任务主线程执行DiscardOldestPolicy丢弃阻塞队列里最老的任务也就是队列里靠前的任务DiscardPolicy 当前任务直接丢弃 新加入一个任务线程池如何进行处理呢【掌握】 新加入一个任务线程池处理流程如下 如果核心线程数量未达到创建核心线程执行如果当前运行线程数量已经达到核心线程数量查看任务队列是否已满如果任务队列未满将任务放到任务队列如果任务队列已满看最大线程数是否达到如果未达到就新建非核心线程处理如果当前运行线程数量未达到最大线程数则创建非核心线程执行如果当前运行线程数量达到最大线程数根据拒绝策略处理 如何将任务提交到线程池中呢 有两种方式execute 和 submit 这两种方式的区别 execute execute 没有返回值execute 无法捕获任务过程中的异常 submit submit 会返回一个 Future 对象用来获取任务的执行结果submit 可以通过 Future 对象来捕获任务中的异常 execute 方式如下 ExecutorService executor Executors.newFixedThreadPool(5); executor.execute(new Runnable() {public void run() {// 执行具体的任务逻辑System.out.println(Task executed using execute method);} }); executor.shutdown();submit 方式如下 ExecutorService executor Executors.newFixedThreadPool(5); FutureString future executor.submit(new CallableString() {public String call() {// 执行具体的任务逻辑return Task executed using submit method;} });try {String result future.get(); // 获取任务执行结果System.out.println(result); } catch (InterruptedException e) {// 处理中断异常 } catch (ExecutionException e) {// 处理任务执行异常 } finally {// 关闭线程池executor.shutdown(); }线程池是如何关闭的呢 通过调用线程池的 shutdown() 方法即可关闭线程池 调用之后会设置一个标志位表示当前线程池已经关闭会禁止向线程池中提交新的任务 去中断所有的空闲线程并且等待正在执行的任务执行完毕通过调用线程 interrupt() 方法当线程池中所有任务都执行完毕之后线程池就会被完全关闭 扩展thread.interrupt() 方法调用后线程会立即中断吗 不会调用 interrupt 只是将被中断线程的中断状态设置为 true通知被中断的线程自己处理中断而不是立即强制的让线程直接中断强制中断不安全 当外部调用线程进行中断的命令时如果该线程处于被阻塞的状态如 Thread.sleep()Object.wait()BlockingQueue#putBlockingQueue#take 等等时那么此时调用该线程的 interrupt 方法就会抛出 InterruptedException 异常 因此可以通过这个特点来优雅的停止线程在 《Java多线程核心技术》 一书中说到将 sleep() 和 interrupt() 搭配使用来停止线程 线程池为什么设计为任务队列满了才创建新线程 这里说一下在知乎上看到的一个问题个人觉得提问的比较好 线程池为什么设计为队列满核心线程数满了才创建新线程而不是队列积压一定阈值的时候创建新的线程 当队列积压满了之后创建非核心线程来执行任务只是一个 兜底措施 你想如果我们自己去设计一个线程池是不是只需要一个参数来管理线程池中的线程数量就可以了完全没必要去创建这些非核心线程执行任务 那么线程池的设计团队可不会考虑的这么简单它们不仅会考虑性能方面更是会保证比较高的 可用性 因为在 Java 应用中高并发 和 高可用 这两块都是比较重要的东西不仅要性能好还要不崩溃 就比如之前滴滴故障、阿里云故障、语雀故障所带来的影响都是比较大的对公司来讲整个可信度有所下降对于我们个人来讲可能有些人恰巧需要紧急使用但是由于发生故障不得已计划延期 所以线程池为了保证 高可用 就设计了任务队列以及在队列满了之后再去创建非核心线程处理溢出来的任务 当然任何设计都是平衡之后的选择如果你在公司项目需求与设计者的理念不符合可以基于原有设计做出封装来进行定制化操作 线程池中线程异常后该线程会销毁吗 向线程池中提交任务有 execute() 和 submit() 两种提交方式的区别如下 execute 执行任务execute 没有返回值无法捕获任务过程中的异常 submit 执行任务submit 会返回一个 Future 对象用来获取任务的执行结果可以通过 Future 对象来捕获任务中的异常 那么执行过程中发生异常线程会销毁吗 execute 无法捕捉任务过程中的异常是因为当任务在执行时遇到异常的话如果异常在线程执行过程中没有被捕获的话该异常就会导致线程停止执行并且在控制台打印异常之后该线程会终止线程池会创建一个新线程来替换他 submit 方式执行任务的话当执行过程中发生异常异常会被封装在 submit() 返回的 Future 对象中当调用 Future.get() 时可以捕获到 ExecutionException 异常因此使用 submit() 发生异常不会终止线程 参考线程池中线程异常后销毁还是复用 关于线程池在生产环境中的使用 这里整理了一些线程池在生产环境中使用的建议来帮助我们更好的在项目中使用线程池 一个项目使用一个线程池还是多个线程池 一般建议是不同的业务使用不同的线程池从而避免非核心业务对于核心业务的影响 如果所有的业务使用同一个线程池非核心业务可能执行速度很慢从而占用了很多线程迟迟不归还导致核心业务在任务队列中等待拿不到线程执行 并且还可能造成 死锁问题 当父子任务使用同一个线程池时父任务如果将核心线程全部占用之后等待子任务完成由于核心线程没有空闲的导致子任务进入到任务队列中等待线程资源导致父子任务之间互相等待 线程池在 RocketMQ 中的使用 在 MQ 中使用了很多线程池这里说一下在发送消息时使用的线程池 1、任务队列创建了 异步发送者线程池 任务队列 使用长度为 50000 的阻塞队列 2、线程数核心线程数 和 最大线程数 相同为 CPU 核数 3、存活时间非核心线程存活时间 60s 4、线程名称重写了线程工厂主要是 为了线程的命名规范 这样在查询日志时只要做好业务之间的隔离就可以很容易的根据线程名称来定位到对应的业务便于分析线上问题 private final ExecutorService defaultAsyncSenderExecutor;private final BlockingQueueRunnable asyncSenderThreadPoolQueue;this.asyncSenderThreadPoolQueue new LinkedBlockingQueueRunnable(50000);this.defaultAsyncSenderExecutor new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),Runtime.getRuntime().availableProcessors(),1000 * 60,TimeUnit.MILLISECONDS,this.asyncSenderThreadPoolQueue,new ThreadFactory() {private AtomicInteger threadIndex new AtomicInteger(0);Overridepublic Thread newThread(Runnable r) {return new Thread(r, AsyncSenderExecutor_ this.threadIndex.incrementAndGet());}});那么我们在自己的项目中使用的线程池就可以参考 MQ 中的用法更加规范的使用线程池 至于为什么要这样设置核心线程数一方面是参考了设置核心线程数的经验CPU 密集型的任务令线程数等于 CPU 核心数减少了线程之间的上下文切换速度比较快另一方面 RocketMQ 肯定内部经过性能测试发现这样设置性能比较好一些 关于线程数量的设置 在项目中一般使用线程池的场景无非就两种 及时性任务 需要迅速完成降低用户等待时间非及时性任务 批量完成任务一般是后台任务 那么对于 及时性任务 来说需要尽可能快的完成任务因此要 尽可能增大可执行任务的线程数量 来尽可能快的完成任务不要设置任务队列 因为只有任务队列满了之后才会去创建非核心线程执行 对于 非及时性任务 来说这类任务并不面向用户特征是任务量很大需要批量处理不需要很低的延迟因此需要设置合适线程数量 利用有限的资源去尽可能快的执行任务 并且设置任务队列去缓冲任务但是尽量不要使用无界的任务队列无界队列任务堆积过多会造成 OOM 这里举一个线程池在高并发电商系统中的使用案例 这里我举一个使用线程池的真实生产环境的案例用户消息推送 对于中大型电商系统来说用户量一般最少都达到了千万级那么如果举办促销活动或者优惠活动了电商系统肯定需要给用户发送通知可能会有多个渠道发送比如短信、邮箱等等那么肯定是需要调用第三方平台的 API 了 调用其他平台 API毫无疑问就会产生网络 IO并且是 千万级别的网络 IO 如果只靠单线程去执行那可能等推送完之后促销活动也已经结束了 因此对于这种 IO 任务并且是大体量推送的 IO 任务就必须引入线程池来优化性能了通过多线程来进行任务的推送当然这里还使用了 RocketMQ 来进行解耦引入 MQ 之后就是使用线程池来生成大量消息推送到 MQ 中消费者再去订阅这些消息去调用第三方平台进行推送由于该文章主要是讲线程池的所以这里 MQ 的部分就简单说一下 ThreadPoolExecutor threadPoolExecutor new ThreadPoolExecutor(0,permits * 2,60,TimeUnit.SECONDS,new SynchronousQueue(),NamedDaemonThreadFactory.getInstance(name) );这里也将线程池创建的代码给列出来这里顺带说一下线程池核心线程的参数为什么设置为 0 因为在消息推送这块并不是一直要推送的促销活动、发优惠券在正常情况下是不会推送发送消息的因此将核心线程数设置为 0 可以在没有推送任务的时候将线程池中的线程都回收掉有任务的时候再来创建非核心线程执行任务这样可以避免线程在没有任务时空闲占用资源 这里注意任务队列的选用 将核心线程数设置为 0 之后队列使用了 SynchronousQueue 因为这个队列是不存储元素的因此有任务来了就会创建非核心线程去执行 如果将设置了有容量的任务队列任务进来之后会先放在队列中并不会创建非核心线程 美团技术团队针对线程池所做的优化 在美团内部有多次因为线程池参数设置不合理而引发故障的案例 因此可以发现在不同场景下开发人员对参数的配置有一个大概的方向但是具体配置多少还没有一个通用的公式 导致上线之后线程池会因为 线程数设置过少 或者 任务队列设置不合理 而出现故障 因此美团技术团队设计了 动态化线程池 提供了对 线程池的监控 以及参数动态调整这样在调整参数之后通过监控可以看到整个线程池的负载情况可以选出比较合适的参数方案 那么这里重点的优化提升就在于两点 线程池参数的动态化设置线程池监控 这里提一下在线程监控中对线程池负载的定义 线程池的负载可以根据活跃的线程数和最大线程数的比值来反映 线程池活跃度 activeCount/maximumPoolSize 当活跃度升高代表着线程池负载在逐步上升 还可以 从任务队列中等待的任务数量 或者 发生拒绝策略的次数 来反映 总结一下 线程池参数的设置没有一个通用的公式要根据实际场景出发在设置之后可以对线程池的性能进行测试像对线程池进行性能测试的话就需要对线程池做监控来看在不同参数下线程池处理任务时的负载表现来设置更加合理的参数 自定义拒绝策略 在线程池中可以 自己去定义拒绝策略 如果线程池无法处理更多的任务了可以在自定义的拒绝策略中将拒绝的任务 异步持久化 到磁盘中去之后再通过一个后台线程去定时扫描这些被拒绝的任务慢慢执行 保证严格的任务不丢失如果线上机器突然宕机线程池的阻塞队列中的请求怎么办 如果宕机重启之后线程池阻塞队列中的任务就会全部丢失 如果想要解决这种情况的话有这么一个 解决方案 在将任务提交到线程池中去的时候先把任务在数据库中存储一份并记录任务执行的状态未提交、已提交、已完成执行完之后的话将任务状态标记为 已完成如果宕机后导致任务丢失就可以去数据库中扫描任务重新提交给线程池执行 阿里手册中的线程池规范 在使用线程池的时候需要注意一些规范以免出现不必要的问题可以参考阿里巴巴 Java 开发手册如下 线程池名称命名规范 线程池创建规范
http://www.hkea.cn/news/14357413/

相关文章:

  • 长沙网站老铁外链
  • 如何做网站的二级页面外贸海外推广
  • 网站开发亿码酷流量外贸新品开发网站
  • 营销型企业网站建设的预算rsd wordpress
  • 上地网站制作wordpress问卷填报主题
  • 使用vue做单页面网站给网站网站做优化
  • 做网站会员登陆e福州便民服务自助终端
  • 昆明php网站建设义乌网站建设公司价位
  • wordpress零基础建站丰城网站建设公司
  • 足球竞猜网站开发计算机专业主要学什么女生
  • 贵州建设监理协会网站怎么把网站管理系统
  • 洛阳网站建设招聘信息友情链接交换网址大全
  • 网站建设服务ysaigo改网站js代码
  • 珠海网站建设杰作美食网站建设背景
  • 网站抠图怎么做的太原工业学院教务网络管理系统
  • 免费优化网站wordpress表单中文版
  • 沙发网站建设城乡和建设部建造师网站
  • 如何建一个外贸网站网站你懂我意思正能量晚上下载
  • 南宁手机端建站模板wordpress添加栏目插件
  • 广东省省建设厅网站网站备案怎么注销
  • 中国做外贸的网站有哪些免费咨询律师在线一对一问答平台
  • 手机微网站开发教程sae wordpress 插件
  • 中山精品网站建设咨询wordpress mysql5.1
  • 上海技术做网站专业做公司网页设计
  • 怎样加盟网站建设专门用于网页制作的软件
  • 摄影网站设计报告dede程序数据库还原图文教程★适合dede网站迁移
  • 毛衣品 东莞网站建设wordpress时间轴源码
  • 义乌门户网站建设济源网站建设价格
  • 网站建设主要包括什么网站视频插件代码
  • 3d全景网站怎么做中国互联网协会成员