多线程应用java.util.concurrent.ThreadPoolExecutor

在java编程中,需要应用多线程的情况还是比较多的,多线程程序编写也有很多方式,最原始的方法,直接new Thread重写run方法,或者是实现Runable。这两种方式本质都是直接new Thread。效率和资源利用率比较低。下面我说一下比较推荐的方式。

A thread pool should be created by ThreadPoolExecutor rather than Executors. These would make the parameters of the thread pool understandable. It would also reduce the risk of running out of system resource.

上面这段英文摘抄自阿里巴巴的java编写规范P3C文档中关于多线程的规范建议。翻译一下:

线程池的创建应当使用ThreadPoolExecutor 而不是Executors。这样可以使线程池创建的参数更容易理解,而且也会降低程序运行发生意外的风险。

既然阿里巴巴关于多线程使用都给出具体类名了,我们也就无须质疑这个的好用性了,下面我们就研究一下ThreadPoolExecutor 这个线程池的使用和参数设置意义基本就可以了。

这个类有很多构造参数,不过构造参数基本都是对类属性的初始化,我们只要搞明白每个属性的意义就基本理解了这个线程池的使用。

Core and maximum pool sizes

一个ThreadPoolExecutor 会自动适应线程池内的线程数量,最小Core ,最大maximum ,当一个新的任务通过 execute方法提交执行时。如果当前线程池内的线程数量小于Core,这时候即使有其他线程处于空闲状态,也会创建一个新的线程执行任务。如果当前线程池内的线程数量大于Core,但是小于maximum ,这时候只有当所有的queue(线程排队策略,一个属性,后面会介绍这个东西)都满队列的情况下才会创建新的线程。当线程池数量等于maximum ,并且所有的queue都满了,就会用到的拒绝策略RejectedExecutionHandler(一个属性,后面会介绍这个东西)。

keepAliveTime

如果当前的线程池数量大于Core,多出的线程在空闲这个时间后会被停止。这个参数的意义是当一个线程执行完任务后,后面的任务还没到达,可以让这个线程等待一定时间在销毁,可以执行后面的任务,而不需要新建线程。


线程queue

Unbounded queues  举例:LinkedBlockingQueue  一个线程无限排队提交过来的任务,这种排队策略线程池一般最多只有Core,因为新提交的任务会在已有的线程中排队执行,而不会新建线程。

Bounded queues  举例: ArrayBlockingQueue  一个有上限数量的排队线程,当线程数量大于Core时,新提交的任务会在queue里面排队执行,当所有的线程queue排满时会创建新的线程。


RejectedExecutionHandler

拒绝策略

AbortPolicy,直接报错,,,

CallerRunsPolicy,在提交任务的线程自己执行。

DiscardPolicy,新提交的任务直接扔掉,执行失败。

DiscardOldestPolicy, 线程中,排序靠前的放弃执行,当有空余线程时在执行,当然也会应为新的任务提交再次失败。


了解上面那么多基本就可以实战使用了,当然还有很有其他属性,策略,甚至很多策略都是可以通过集成重写的方式自己实现,这就是高阶一点的了,对于一般的需求,知道这些基本够了。



你可能感兴趣的:(java运用)