以前,我们都通过消耗特定CPU资源的线程的创建和破坏创建线程,因此在高并发下创建线程的方法将严重影响代码的执行效率。线程池的作用是让一个池的作用执行执行后立即将线程销毁,并继续执行新任务,从而保存连续创建线程和破坏线程的开销。
创建Java线程池的核心类别是:
它提供了四个构造函数来创建一个线程池。核心构造函数如下所示:
这7个参数的含义如下:
通过此构造函数创建线程池时,这些参数必须满足以下条件,否则将被抛弃:
此外,工作标语,线程捕获和处理程序不能为空,否则会抛出空的指针异常。
让我们以一些示例来深入了解这些参数的含义。
使用上述构造函数创建一个线程池:
上面的代码创建了许多核心线程,最大线程数为2,最大活动时间为10秒,线程队列长度为1。
如果我们通过执行方法向线程池提交任务,以查看结果:
执行和提交ThreadPoolExecutor的方法可以将任务提交到线程池。区别在于,提交方法可以返回执行结果并返回值类型。
睡眠方法代码:
核心线程线程线的数量为1。线程池中的线程是1.在添加的,因为提交的任务是由核心线程执行的,因此无需将线程放在线程队列中并等待。线队列长度为0。
如果我们通过执行方法向线程池提交两个任务,以查看结果:
核心线程线程的数量为1。线程池中的活动线程数为1.由于核心线程的数量为1,因此不能在这100秒内执行其他任务,因此将其放置在线程队列中并等待。线队列长度为1。
如果我们通过执行方法向线程池提交3个任务,以查看结果:
这三个任务是休眠100秒,因此核心线程池中的第一个任务正在执行,第二个任务放入线程队列中。提交第三个任务后,线程队列已满(我们定义的长度是1)。由于线程池允许的最大线程数为2,因此线程池还可以创建一个线程来执行另一个任务以执行另一个任务。第三个任务放入线程队列中。
更改第二和第三任务的睡眠时间,并观察输出:
提交任务5秒后,任务完成了,因此执行了线程队列中的任务,因此线程数为0,活动线程的数量为2(第一个和第三任务)。秒,第三个任务完成了,因此活动线程的数量为1(前100秒尚未执行)。
在第三任任务结束时,我们观察到线程快照:
可以看出,线程池中有两个线程。Thread-0在第一个任务(睡100秒,不结束)中执行,执行第三任任务后不会立即破坏Thread-1。一段时间(10秒后),请观察线程快照:
可以看出,螺纹线程1被破坏,因为当我们创建一个线程池时,keyivEtime指定keyiveTime 10秒钟。10秒钟后,将破坏核心线程池螺纹范围之外的线。
如果一次提交4个任务以查看它将是什么:
由于我们设定的拒绝策略是流产的,因此我最终提交的任务直接被拒绝。下面将介绍更多的拒绝策略。
线程池包含以下状态:
当处理线程池中的所有任务时,线程将不会单独关闭。我们可以通过调用和方法关闭线程池。两者之间的区别为:
以两个示例观察两者之间的区别:
例子:
启动程序,控制台输出如下:
可以看出,尽管在提交任务后立即执行该方法,但它不会立即关闭线程池,而是等待所有提交的任务在关闭之前执行。
例子:
启动程序,控制台输出如下:
可以看出,在执行方法后,线程池立即关闭,执行下的两个任务被中断,并且等待线程队列中执行的两个任务返回到线程队列。
通过上面的两个示例,我们还可以看到该方法都没有阻止。通常使用匹配方法。
接收时间和单元的超时参数的方法。等待设置时间时,如果关闭,则将监视执行人员服务。如果关闭它,它将返回true,否则将返回错误。该方法正在阻止:
启动程序输出如下:
当线程池无法接收新任务时,可以采取以下四个策略:
策略:该任务由呼叫线程处理:
上面的线程池一次只能一次提交4个任务。提交第五任务后,将被策略处理拒绝。启动程序输出如下:
可以看出,第五项提交的任务是由呼叫线程(即主线程)处理的。
策略:丢弃任务并提出异常。先前的示例是使用此策略,因此不再证明。
策略:丢弃放入线程队列的第一个任务,将新提交的任务放在线程队列的结尾处:
启动程序输出如下:
可以看出,最终提交的任务已执行,第三个任务是将第一个任务放在线程队列中并被丢弃。
策略:直接丢弃新任务,而不是异常:
启动程序,输出如下:
第五任务直接被拒绝并放弃,而没有抛出任何异常。
除了使用ThreadPoolExecutor的构造函数创建线程池外,我们还可以使用提供的出厂方法来创建不同类型的线程池:
查看方法源代码:
可以看出,通过创建固定的尺寸线程池,大小由参数指定。它具有以下特征:
查看方法源代码:
这是一个理论线程池:
查看源代码:
查看源代码:
因此,理论是您也可以收到无限的任务。延迟工作也是一个无限的队列。
除了由NewsCheduledThreadPool创建的线程池,除了处理普通可运行的任务外,它还具有调度的功能:
1.指定的时间执行后延迟:
2.以指定的速率执行:
3.根据指定的延迟执行:
乍一看,ScheduletFixEdrate和ScheduleWithFixedlay并没有什么不同。实际上,它们仍然有区别:
为了使用这些线程池工厂,阿里巴巴的编程法规指出:
由于这些线程池理论可以接收无限的任务,因此存在内存溢出的风险。企业。一般线程池的创建可以参考以下规则:
可以使用CPU核心号:
ThreadPoolExecutor提供了几种判断线程池状态的方法:
程序输出如下:
正如我们之前提到的,即使核心线程线程是免费的,即使核心线程也不会被销毁,除非将核心线程用于超时:
程序输出如下所示:
5秒钟后,执行任务,核心线程是空闲的。由于核心线程超时是通过该方法设置的,因此核心线程在3秒内被销毁(keepalivetime设置)。核心线程被销毁后,线程池,没有效果,因此自动关闭。
值得注意的是,如果线程池称为方法,则不能为0。
ThreadPoolExecutor提供了一种查看其源代码的方法:
可以看出,它删除了线程队列中的任务,而不是要执行的任务。例如:
执行程序,输出如下:
可以看出,由于唯一的核心线程已经执行任务,因此尚未执行任务并已删除任务,因此稍后提交的任务放在线程队列中,然后通过删除方法删除。
默认情况下,仅当任务被提交到线程池时,线程池才会启动核心线程处理任务。通过调用方法,我们可以让核心线程处于活动状态,即使没有没有任务提交:
程序输出如下所示:
此方法返回布尔类型值,因此,如果启动了核心线程,则返回false,否则返回了TRUE。
它也有类似的方法。它的角色是一次启动所有核心线程,以便它正在积极地等待任务执行任务。
线程poolexecutor的调用方法用于在任务集中随机执行任务并返回执行结果。该方法是一种同步方法:
启动程序,输出如下:
ThreadPoolExecutor的InvoKeall是执行任务集中的所有任务,并返回未来集合:
输出如下:
总结这些方法:
AllowCoreThReadTimeOut(布尔值)允许核心线程在时间后暂停。如果超时后核心线程被销毁,则线程池自动关闭等待端口(长时间,timeUnit单元)以阻止当前线程。Execute(runnable命令)将任务提交到线程池而不返回提交(运行任务)的情况下,将任务提交到线程池中,并返回futureisshutdown()以确定线程池是否为关闭状态。池是否已关闭删除(可运行的任务)删除线程队列queue PrestartCoreThread()中的指定任务提前处于活动状态处于活动状态,等待执行任务prestartallCoreThreads()将所有核心线程提前在活动状态中,等待执行任务getActiveCount()get cetCorePoolSize()getCorePoolSize()线程池核心线程threadpoolexecutor.getqueue()获取线程池池行队列queue getmaximumpoolsize()以获取最大线程pool pool()以允许线程池处于粪便状态,不再接收任务,不再接收任务,不再接收任务,并且不再接收任务,并且不再接收任务,在所有任务运行后,关闭线程pool.shutdownnow()允许线程池处于停止状态,不再接受任务,尝试中断操作中的任务,关闭线程池并返回线程队列中的任务。