线程池怎么创建线程(线程池创建线程的好处)

dylinchen 948 2022-11-01

本文目录一览:

线程池创建的4种方式与参数详解

Executors 是 Executor 的工具类,提供了4种创建不同线程池的方式,来满足业务的需求。底层是调ThreadPoolExecutor类构造方法。

newFixedThreadPool:创建的是定长的线程池,可以控制线程最大并发数,超出的线程会在线程队列中等待,使用的是无界队列,核心线程数和最大线程数一样,当线程池中的线程没有任务时候立刻销毁,使用默认线程工厂。

newSingleThreadExecutor:创建的是单线程化的线程池,只会用唯一一个工作线程执行任务,可以指定按照是否是先入先出,还是优先级来执行任务。同样使用无界队列,核心线程数和最大线程数都是1个,同样keepAliveTime为0,可选择是否使用默认线程工厂。

newCachedThreadPool:设定一个可缓存的线程池,当线程池长度超过处理的需要,可以灵活回收空闲线程,如果没有可以回收的才新建线程。没有核心线程数,当线程没有任务60s之后就会回收空闲线程,使用有界队列。同样可以选择是否使用默认线程工厂。

newScheduledThreadPool:支持线程定时操作和周期性操作。

Executors工具类创建线程池底层是调ThreadPoolExecutor构造方法。

1、ThreadPoolExecutor4个创建线程池的构造方法:

2、参数详解

corePoolSize:核心线程数量。当线程数少于corePoolSize的时候,直接创建新的线程,尽管其他线程是空闲的。当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中。

maximunPoolSize:线程池最大线程数。只有在缓冲队列满了之后才会申请超过核心线程数的线程。当线程数量大于最大线程数且阻塞队列满了这时候就会执行一些策略来响应该线程。

workQueue:阻塞队列。存储等待执行的任务,会对线程池的运行产生很大的影响。当提交一个新的任务到线程池的时候,线程池会根据当前线程数量来选择不同的处理方式。

keepAliveTime:允许线程的空闲时间。当超过了核心线程数之外的线程在空闲时间到达之后会被销毁。

unit:keepAliveTime的时间单位。

threadFactory:线程工厂。用来创建线程,当使用默认的线程工厂创建线程的时候,会使得线程具有相同优先级,并且设置了守护性,同时也设置线程名称。

handler:拒绝策略。当workQueue满了,并且没有空闲的线程数,即线程达到最大线程数。就会有四种不同策略来处理

待补充。

参考资料

线程池的创建

new ThreadPoolExecutor(corePoolSize, maxinumPoolSize, keepAliveTime, milliseconds, runnableTaskQueue, handler);

参数简介:

当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其它空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不会再创建。如果调用了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有基本线程。

用于保存等待执行的任务的阻塞队列,可以有以下选择:

ArrayBlockingQueue :是一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原则对元素进行排序

LinkedBlockingQueue :一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量通常高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。

SynchronousQueue :一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态。吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool()使用了这个队列。

PriorityBlockingQueue :一个具有优先级的无限阻塞队列

线程池被允许创建的最大线程数,如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。需要注意的是,如果使用了无界的阻塞队列,那么这个参数也就没什么效果。

当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。在JDK1.5中Java线程池框架提供了以下4中策略。

AbortPolicy :直接抛出异常

CallerRunsPolicy :只用调用者所在线程来运行任务

DiscardOldestPolicy :丢弃队列里最近的一个任务,并执行当前任务

DiscardPolicy :不处理,丢弃掉

线程池的工作线程空闲后,保持存活的时间。所以如果任务很多,每个任务执行的时间比较短,可以调大时间,提高线程的利用率

可选单位有天(DAYS)、小时(HOURS)、分钟(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)、纳秒(NANOSECONDS,千分之一微秒)


线程池的四种创建方式及区别

核心线程数为0,非核心线程数为MAX_VALUE,

队列不存储值,总认为队列是满的,所以每次执行任务时都会创建非核心线程,非核心线程空闲了超过60秒(默认),就会自动回收。

2.newfixedThreadPool 创建定长的线程池

在达到长度之前,每提交一个任务都会创建一个线程,如果达到线程池最大数量,则提交到队列中,在空闲的时候也不会自动回收线程

核心线程数为参数传入,非核心线程数和核心线程数一样,

队列为无界队列,资源有限的时候容易引起OOM.

与newSingledThreadPool 不同的是核心线程数不为1.

3.newSingledThreadPool 创建单一线程执行。

只有一个线程按顺序执行任务,如果这个线程出现异常结束,会有另一个线程取代并按顺序执行。

corepoolsize 核心线程数为1 ,非核心线程数为1 ,

队列为无界队列,

单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。

4.newScheduedThreadPool 创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。如果延迟3秒执行或每隔3秒执行一次

核心线程数为 参数设定,非核心线程数为MAX_VALUE

定义了一个DelayedWorkQueue,它是一个有序队列,会通过每个任务按照距离下次执行时间间隔的大小来排序;

线程池执行逻辑说明:

判断核心线程数是否已满,核心线程数大小和corePoolSize参数有关,未满则创建线程执行任务

若核心线程池已满,判断队列是否满,队列是否满和workQueue参数有关,若未满则加入队列中

若队列已满,判断线程池是否已满,线程池是否已满和maximumPoolSize参数有关,若未满创建线程执行任务

若线程池已满,则采用拒绝策略处理无法执执行的任务,拒绝策略和handler参数有关

拒绝策略

拒绝策略 = 默认采用的是AbortPolicy拒绝策略,直接在程序中抛出RejectedExecutionException异常【因为是运行时异常,不强制catch】,这种处理方式不够优雅。处理拒绝策略有以下几种比较推荐:

在程序中捕获RejectedExecutionException异常,在捕获异常中对任务进行处理。针对默认拒绝策略

使用CallerRunsPolicy拒绝策略,该策略会将任务交给调用execute的线程执行【一般为主线程】,此时主线程将在一段时间内不能提交任何任务,从而使工作线程处理正在执行的任务。此时提交的线程将被保存在TCP队列中,TCP队列满将会影响客户端,这是一种平缓的性能降低

自定义拒绝策略,只需要实现RejectedExecutionHandler接口即可

如果任务不是特别重要,使用DiscardPolicy和DiscardOldestPolicy拒绝策略将任务丢弃也是可以

public class ThreadTest {

// ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);

//

// scheduledThreadPool.scheduleAtFixedRate(new Runnable() {

// public void run() {

// System.out.println("delay 1 seconds, and excute every 3 seconds");

//

// }

//

// }, 1, 3, TimeUnit.SECONDS);

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:文件IO流
下一篇:小程序编程入门(自学小程序编程)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~