线程池的3大方法,7大参数,执行原理,拒绝策略

线程池的3大方法,7大参数,执行原理,拒绝策略

线程池的好处

1)降低资源的消耗 2)提高响应的速度 3)方便管理 4)线程复用、可以控制最大并发数、管理线程

1、三大方法:

Executors.newSingleThreadExecutor(); //单线程

Executors.newFixedThreadPool(5);// 固定线程个数

Executors.newCachedThreadPool(); //缓存池,可扩展,遇强则强,遇弱则弱,最大值为Integer的界,约21亿

注意:实际使用线程池最好不使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池

规则,规避资源耗尽的风险

说明: Executors 返回的线程池对象的弊端如下:

1) FixedThreadPool和SingleThreadPool:

允许的请求队列长度为Integer .MAX_ VALUE, 可能会堆积大量的请求,从而导致OOM

2) CachedThreadPool 和ScheduledThreadPool:

允许的创建线程数量为Integer .MAX_ VALUE,可能会创建大量的线程,从而导致OOM

2、七大参数:(自定义创建线程池)

 public ThreadPoolExecutor(int corePoolSize, //常驻核心线程数
                           int maximumPoolSize, //最大线程数
                           long keepAliveTime, //空闲线程存活时间(数字)
                           TimeUnit unit, //空闲线程存活时间(单位)
                           BlockingQueue<Runnable> workQueue, //任务队列
                           ThreadFactory threadFactory, //线程工厂,一般不动
                           RejectedExecutionHandler handler); //拒绝策略

核心线程

线程池一创建号就会创建并开启这些线程

最大线程数的确定的方法

最大线程数为这个线程池能创建的最大线程数量

1)CPU密集型:看本机的逻辑CPU为几核最大线程数就为几

原因:因为这样可以达到最大并行的线程数,效率最高

附:Runtime.getRuntime().availableProcessors();//获取cpu核数

2)IO密集型:先判断程序中十分消耗IO的线程数量,最大线程数再乘以2

原因:IO操作耗时量大,并且占用资源也大,所以先分配同等数量的线程去执行这些IO线程,再分配大于该数量的线程,一般是2倍

空闲线程存活时间

除开核心线程数,剩余的线程过了设置的空闲线程存活时间后,会自杀,但核心线程你主动关闭是不会自杀的

任务队列

存放等待执行线程的队列,一般用BlockingQueue阻塞队列,除此之外还有BlockingDueue双端队列、SynchronousQueue同步队列等等

线程工厂

线程池的线程由线程工厂创建,一般默认Executors.defaultThreadFactory(),不改

拒绝策略

当线程数量大于最大线程数+任务队列时,所采取的策略

3、执行原理:

1)corePoolSize 个线程处理任务 2)多余的任务在任务队列中等待 3)任务队列满了之后,线程池的线程数会扩容到 maximumPoolSize 4)线程池最大承载能力满了(任务队列+maximumPoolSize),拒绝任务

举个形象好理解的例子

场景:银行排队办理业务,五个柜台,两个开着(1、2),三个暂时关闭(3、4、5),有三个候客区位置

人少的时候:1~5个人(小于核心线程数量+阻塞队列长度)一起来,则只使用已经开着的柜台(核心线程),剩下的在候客区等待并排队(阻塞队列),并且候客区按前来的先办理业务的顺序排队(队列的FIFO)

人多的时候:6~8个人(大于核心线程数量+阻塞队列长度,小于最大线程数+阻塞队列长度)一起来,这些线程通过操作系统时间片的轮转调度算法分配,先来的去1、2号柜台办理业务(核心线程),后来的在候客区等待并排队(阻塞队列),剩下的由于还有人,就会开启3、4、5暂时关闭的柜台(最大线程-核心线程),来给客户办理业务

人超级多的时候:大于8个人(大于最大线程数量+阻塞队列长度)一起来,由于像上种情况,已经满功率进行招待了,还是不够,则除了先来的8个人,剩余的人则被拒之门外(拒绝策略)

4、拒绝策略:

AbortPolicy(默认):直接抛出RejectedExecutionException异常阻止系统正常运行。

银行满了(大于最大线程数+阻塞队列),还有人进来,不处理这个人的,抛出异常!

DiscardPolicy:丢弃无法处理的任务,不会抛出异常。(如果允许任务丢失,这是最好的一种策略)

银行满了(大于最大线程数+阻塞队列),还有人进来,不处理这个人的,不会抛出异常!

DiscardOldestPolicy:抛弃队列中等待最久的任务,重新提交当前任务。

银行满了(大于最大线程数+阻塞队列),尝试去和最早的竞争(第一个办理业务的人),也不会抛出异常!

CallerRunsPolicy(调用者运行):由调用线程(提交任务的线程)处理该任务。

银行满了(大于最大线程数+阻塞队列),哪来的去哪里(从main线程来的就该给main线程自己去处理)!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java线程池是一种用于管理和复用线程的机制,它可以提高多线程应用程序的性能和可靠性。线程池中的线程可以被重复使用,避免了频繁创建和销毁线程的开销。 Java线程池的工作原理如下: 1. 创建线程池:通过ThreadPoolExecutor类创建一个线程池对象,可以指定线程池的核心线程数、最大线程数、线程空闲时间等参数。 2. 提交任务:将任务提交给线程池,可以使用execute()方法提交Runnable任务,也可以使用submit()方法提交Callable任务。 3. 任务队列:线程池会维护一个任务队列,用于存储提交的任务。如果当前线程池中的线程数小于核心线程数,线程池会创建新的线程来执行任务;如果当前线程池中的线程数已经达到核心线程数,任务会被放入任务队列等待执行。 4. 执行任务:当任务队列中有任务时,线程池中的空闲线程会从任务队列中取出任务并执行。如果任务队列为空且当前线程池中的线程数超过核心线程数,空闲线程会等待一段时间后被销毁。 5. 拒绝策略:如果任务队列已满且当前线程池中的线程数已达到最大线程数,新提交的任务会根据指定的拒绝策略进行处理,常见的拒绝策略有抛出异常、丢弃任务、丢弃最旧的任务等。 6. 线程池状态:线程池有几种状态,包括运行、关闭、停止等。可以通过调用shutdown()方法来关闭线程池,调用shutdownNow()方法来停止线程池

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值