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

知乎怎么做自己网站推广产品seo刷排名工具

知乎怎么做自己网站推广产品,seo刷排名工具,网站开发阶段怎么做测试,发布自己的做家教的网站文章目录 一、为什么要用线程池1.1 单线程的问题1.2 手动创建多线程的问题1.3 线程池的作用(优点)1.4 线程池的使用场景 二、线程池的基础知识2.1 线程池的核心组件2.2 JUC中的线程池架构2.3 线程池的配置参数2.4 线程池常见的拒绝策略(可自定…

文章目录

  • 一、为什么要用线程池
    • 1.1 单线程的问题
    • 1.2 手动创建多线程的问题
    • 1.3 线程池的作用(优点)
    • 1.4 线程池的使用场景
  • 二、线程池的基础知识
    • 2.1 线程池的核心组件
    • 2.2 JUC中的线程池架构
    • 2.3 线程池的配置参数
    • 2.4 线程池常见的拒绝策略(可自定义)
    • 2.5 线程池的生命周期
    • 2.6 线程池的任务调度规则
    • 2.7 线程池执行器的钩子方法
  • 三、使用基础
    • 3.1 常见的工作队列
    • 3.2 Executors提供的线程池
    • 3.3 使用Executors创建线程的问题
  • 四、开发实践
    • 4.1 线程数量配置
    • 4.2 提交任务:以submit(callable)为例
    • 4.3 关闭线程池
  • 参考

一、为什么要用线程池

1.1 单线程的问题

单线程无法利用CPU的多核资源,且存在阻塞问题。使用单个线程来处理一组任务,若当前任务阻塞了线程,该线程将失去CPU的使用权,而不是去执行其他可以执行的任务。

1.2 手动创建多线程的问题

需要开发人员去管理线程的生命周期,麻烦,且可能出错。
还存在并发数不可控的问题,如每次到达一个任务时都新建一个线程来处理,当大量任务到达时,会创建大量的线程,导致线程间的竞争加剧,且可能导致系统资源耗尽。

1.3 线程池的作用(优点)

  • 节省线程创建和销毁的开销:线程池通过复用一组线程,可以节省频繁创建和销毁线程的开销。
  • 控制并发数:线程池可以控制最大并发数,避免线程过多导致系统资源耗尽。
  • 提高响应速度:当任务到达时,可以直接使用线程池中已经创建好的线程,节省了新建线程的时间。
  • 管理线程:线程池负责内部线程的生命周期管理,包括创建、销毁和调度等,无需人工干预。

1.4 线程池的使用场景

  • 处理并发请求:每个请求都要一个线程来处理,使用线程池来复用一组线程,能节省创建和销毁线程的开销。
  • 执行异步任务:避免耗时操作(如邮件发送、文件上传)阻塞主线程,可以使用线程池来异步执行这些任务。
  • 处理IO密集型任务:线程在进行IO操作时会阻塞,使用线程池来调度这些任务,可以在任务阻塞时调度其他任务继续执行,避免CPU空闲。
  • 处理计算密集型任务:使用线程池来执行计算密集型任务,可以充分利用CPU的多核资源,也能控制并发数量避免系统资源耗尽。
  • 后台服务:利用线程池来执行后台服务,与前台线程的执行独立,互不影响。
  • 执行定时任务与周期性任务:可以使用ScheduledThreadPool在后台执行这些任务,与前台线程的执行独立。

二、线程池的基础知识

2.1 线程池的核心组件

  • 线程池管理器:负责线程池的创建、销毁、管理和配置。
  • 工作线程:工作线程是线程池中的实际工作者,负责执行提交给线程池的任务。
  • 任务接口:每个提交到线程池的任务都需要实现一个任务接口。Runnable用于定义无需返回值的任务,而Callable则用于定义可以有返回值的任务,并且可以抛出异常。
  • 工作队列(任务队列):用于暂存等待被执行的任务,有多种实现方式,未必是先进先出。
  • 线程工厂:线程工厂的作用是定义一个规范来创建线程,允许在创建线程时进行定制化设置,例如设置线程的名称、优先级、是否为守护线程(daemon thread)等属性。
  • 拒绝策略:见后。
    (后三个核心组件是线程池的后三个配置参数)

2.2 JUC中的线程池架构

Executor
是线程池管理器的顶层接口,只定义了一个方法void execute(Runnable command),用来提交Runnable任务。

ExecutorService
该接口扩展了Executor,增加了更多管理线程池的方法,如提交Callable任务、提交批量任务、线程池的生命周期管理(shutdown()shutdownNow())、获取线程池状态等。

AbstractExecutorService实现了该接口中的部分方法,为创建自定义的线程池服务实现提供了基础框架。

ThreadPoolExecutor继承自AbstractExecutorService,是JUC中线程池管理器的核心实现类。

Executors是一个静态工厂类,提供了多种线程池管理器。

ScheduledExecutorService
该接口扩展了ExecutorService,增加了定时执行和周期性执行任务的功能。ScheduledThreadPoolExecutor实现该接口,专为计划任务而设计。
在这里插入图片描述

2.3 线程池的配置参数

  • corePoolSize:核心线程数。
  • maximumPoolSize:最大线程数。
  • keepAliveTime:空闲线程存活时间。当线程池中的工作线程数量超过核心线程数时,额外的工作线程在空闲这个时间段后会被终止,直到工作线程数量降到核心线程数。但如果设置了allowCoreThreadTimeOuttrue,那么核心线程也可以被终止。
  • unit:空闲线程存活时间的单位,可以用枚举类TimeUnit设置。
  • workQueue:工作队列。
  • threadFactory:线程工厂。
  • handler:拒绝策略。当阻塞队列已满且工作线程数大于等于最大线程数时,无法接受新的任务,会按照拒绝策略进行处理。

2.4 线程池常见的拒绝策略(可自定义)

  • AbortPolicy:拒绝策略。是默认策略,会将新任务拒绝,并且抛出RejectedExecutionException异常。
  • DiscardPolicy:抛弃策略。会将新任务丢掉,但不会跑出异常。
  • DiscardOldestPolicy:抛弃最老任务策略。不是丢弃新任务,而是先丢弃最先进入队列的任务,然后将新任务入队。
  • CallerRunsPolicy:调用者执行策略。让提交任务的线程去执行新任务,而不是使用线程池中的线程去执行。
    在这里插入图片描述

2.5 线程池的生命周期

  • New:新建状态。当线程池创建后,但尚未开始执行任务时,它处于新建状态。此时,线程池中的线程尚未启动。
  • Running:运行状态。新建的线程池开始接受并处理任务后就会进入运行状态,这是线程池的正常工作状态,可以接收新任务和处理工作队列中的任务。
  • Shutdown:关闭状态。调用shutdown()方法后,线程池会进入关闭状态。此时,线程池不再接受新任务,但不会立刻终止,它会继续处理队列中已有的任务直到所有任务完成。
  • Stop:停止状态。调用shutdownNow()方法后,线程池会进入停止状态,此时会中断正在执行任务的线程,清空任务队列,并返回未开始执行的任务列表。
  • Tidying:整理状态。完成关闭状态或停止状态的工作后,线程池会进入整理状态。此阶段,线程池中的线程数量降为0,即将调用terminated()钩子方法。
  • Terminated:终止状态。在整理状态后,线程池调用terminated()方法并进入终止状态。此时线程池生命周期结束,会释放所有资源。
    在这里插入图片描述

2.6 线程池的任务调度规则

当向线程池提交一个任务时:

  1. 若线程池中的工作线程数量小于核心线程数,执行器总是优先创建一个新的工作线程来执行任务,而不是使用一个空闲的工作线程(目的是快速让线程池中有足够的活跃线程)。若工作线程数量大于等于核心线程数,则根据工作队列的情况进行相应的处理。
  2. 若工作队列未满,则将任务入队。若工作队列已满,则根据工作线程数量与最大线程数的关系进行相应的处理。
  3. 若工作线程数大于等于最大线程数,则执行拒绝策略。否则,会新建一个非核心线程来立即执行新的任务。
    在这里插入图片描述

2.7 线程池执行器的钩子方法

beforeExecute(Thread t, Runnable r): 任务执行之前的钩子方法。
afterExecute(Runnable r, Throwable t): 任务执行之后的钩子方法。
terminated(): 线程池终止时的钩子方法。

三、使用基础

3.1 常见的工作队列

工作队列基于阻塞队列实现,我们可以实现BlockingQueue来自定义阻塞队列,也可以使用JUC中提供的阻塞队列:

  • ArrayBlockingQueue:基于数组的有界阻塞队列。队列大小是固定的,在创建时必须指定。由于是基于数组,所以访问速度快,但可能有扩容受限的问题。
  • LinkedBlockingQueue:基于链表的阻塞队列。如果不指定容量,则默认为Integer.MAX_VALUE。相比ArrayBlockingQueue,插入和删除操作可能稍微慢一点,但由于链表的动态性,它可以更灵活地调整大小。
  • PriorityBlockingQueue:基于最小堆的无界的优先级队列,元素按照自然排序或提供的比较器进行排序。任务按照优先级顺序被处理,而非先进先出。
  • DelayQueue:基于PriorityBlockingQueue的无界阻塞队列,其中元素只有在延迟期满后才能被获取,否则将阻塞等待,常用于实现定时任务和延迟操作。
  • SynchronousQueue:一个特殊的队列,它没有内部容量,每个插入操作必须等待另一个线程的对应移除操作,反之亦然。适用于直接的生产者-消费者传递,非常适合传递性操作。
  • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列,支持公平和非公平模式。它还提供了一个tryTransfer()方法,允许生产者直接将元素转移给等待中的消费者,如果没有消费者等待,则可以选择是否阻塞(生产者可阻塞)。
  • LinkedBlockingDeque:双向链表实现的双向阻塞队列,既可以用作栈,也可以用作队列。它支持有限或无界的队列,并提供了putFirst()putLast()等方法来控制元素的插入位置。

3.2 Executors提供的线程池

在这里插入图片描述

3.3 使用Executors创建线程的问题

  • 定长线程池/单线程话线程池:阻塞队列无界,可能导致JVM出现OOM(Out Of Memory)异常。
  • 定时线程池/可缓存线程池:最大线程数量不设限上,如果任务提交较多,就会造成大量的线程被启动,可能造成OOM异常,也可能导致CPU线程资源耗尽。

四、开发实践

4.1 线程数量配置

IO密集型
核心线程数设置得比CPU核心数稍大,因为当线程在等待I/O时,CPU可以调度其他线程执行。最大线程数可以设置得更高,甚至远大于CPU核心数,具体数值取决于系统的I/O能力及预期的并发水平。一般推荐设置为2 * CPU核心数或更高,但需注意不要设置得过高以免过度消耗系统资源。
计算密集型
核心线程数和最大线程数通常设置为CPU核心数,因为在这种情况下,更多的线程并不能带来性能提升,反而会因为上下文切换带来额外开销。

4.2 提交任务:以submit(callable)为例

	 // 创建线程池ExecutorService executor = Executors.newSingleThreadExecutor();// 创建Callable任务对象Callable<Result> task = () -> {// ...};// 提交任务并获取Future对象Future<Result> future = executor.submit(task); // 提交任务并获取Future// 获取结果try {// get()方法会阻塞,如果任务执行过程中发生了异常,那么此处会抛出该异常Result res = future.get();} catch (InterruptedException e) {// 处理中断异常...} catch (ExecutionException e) {// 处理执行异常...}// 关闭ExecutorServiceexecutor.shutdown();

4.3 关闭线程池

调用shutdown()shutdownNow()后,当前线程不会等待线程池的关闭,若当前线程结束了,可能导致内存泄露和资源浪费。

若线程池中还有活动的线程,就算主线程结束了,JVM也会因为存在活跃的非守护线程而无法退出,导致应用程序无法正常退出。

awaitTermination()方法用来阻塞当前线程,直到线程池中的所有任务完成执行或者超时,或者当前线程被中断。可以用于等待线程池中的线程全部执行完后再退出当前线程,线程池中的所有线程在超时前执行完毕,会返回true并恢复当前线程的执行。

ExecutorService executorService = Executors.newFixedThreadPool(10);// ... 提交任务到线程池// 关闭线程池
executorService.shutdown();
try {// 等待一定时间,直到超时或者线程池中的线程全部执行结束if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {// 如果超时,则尝试强制关闭executorService.shutdownNow();// 等待一定时间,直到超时或者线程池中的线程全部执行结束if (!executorService.awaitTermination(60, TimeUnit.SECONDS))System.err.println("线程池未在规定时间内停止!");}
} catch (InterruptedException ie) {// 强制终止线程池executorService.shutdownNow();// 保持当前线程的中断状态Thread.currentThread().interrupt();
}

参考

Java线程池(超详细)
Java 多线程:彻底搞懂线程池

http://www.dinnco.com/news/65390.html

相关文章:

  • 代网站备案费用网站建设策划书案例
  • 很多网站开发没有框架如何制作的友博国际个人中心登录
  • 和小孩做的网站91永久免费海外地域网名
  • 做动漫网站要多少钱百度seo关键词优化推荐
  • 湛江网站制作建设网络推广的方法
  • 90设计网站真实稿费域名查询ip网站
  • 深圳卫生人才网官网优化的近义词
  • 做照片书的模板下载网站b站推广入口
  • 义安区住房和城乡建设局建网站杭州百度推广公司有几家
  • 可以做直播源的佛教网站短视频广告投放平台
  • 山东济宁曲阜疫情最新情况温州seo网站推广
  • 如何在网站做qq群链接seo技术外包
  • 做网站 江门网页制作教程视频
  • 网站网站建设网页设计web成品网站源码免费
  • 青岛专业网站营销温岭网络推广
  • 网站建设所操作是什么网站推广引流
  • 南宁市住房和城乡建设局网站百度sem是什么
  • 网站建设比较好百度主页网址
  • 烟台微网站建设天津百度优化
  • 做动态效果的网站seo关键词排名优化销售
  • 网站seo排名优化工具品牌公关案例
  • 网站建设的实训技术总结怎么快速推广app
  • 重庆网站建设的价格达内教育
  • 重庆网站制作今天的新闻联播
  • 如何做网站好的竞价托管公司
  • 公司注册网站入口5118网站如何使用免费版
  • 购物网站后台好管理吗百度竞价渠道户
  • 赌博网站建设网站建设的系统流程图
  • 政府网站用什么颜色全网营销型网站
  • 做彩票网站代理犯法吗6seo快速排名软件品牌