一、什么是线程池
线程池:指在初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时重用这些线程而不是新建一个线程,一旦任务已经完成了,线程回到池子中并等待下一次分配任务。
二、线程池原理
将任务提交给线程池,由线程池分配线程、运行任务,并在当前任务结束后复用线程。
三、线程池的好处
1)减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,执行多个任务;
2)运用线程池能有效的控制线程最大并发数,防止抢占系统资源从而导致阻塞;
3)能对线程进行一些简单的管理。比如:延时执行、定时循环执行的策略等。
四、线程池的接口与类简单介绍
(一)涉及到的接口与类
常用的线程池接口和类都在 java.util.concurrent包下,大致为:
Executor:线程池的顶级接口
ExecutorService:线程池接口,可通过submit()方法提交任务代码
Executors工厂类:通过此类可以创建一个线程池
ExecutorService接口的实现类最常用的为以下两个:
1)ThreadPoolExecutor
2)ScheduledThreadPoolExecutor
Executors工厂类创建线程池的方法大致有以下几种:
1)newFixedThreadPool:创建指定的、固定个数的线程池
2)newCachedThreadPool:创建缓存线程池(线程个数根据任务数逐渐增加,没有上限)
3)newSingleThreadExecutor:创建单个线程的线程池
4)newScheduledThreadPool:创建调度线程池 调度:定时、周期执行
其中newFixedThreadPool()方法应该是我们最常使用的。
(二)简单小结
也就是说,在我们的开发中,最常见的使用线程池的方式为:
通过Executors工厂类的newFixedThreadPool()方法来创建指定线程个数的线程池。
五、线程池的使用
(一)使用步骤
1)创建线程池对象
2)创建线程任务
3)使用线程池对象的submit()方法提交要执行的任务
4)使用完毕,可以使用shutdown()方法关闭线程池
(二)使用案例
需求:使用线程池管理线程来简单的模拟买票程序。
代码实现:
1 | public class Demo01(){ |
针对上述代码的补充解释:
1、关于提交任务至线程池:
仔细观察,你会发现其实每次提交的都是同一个任务对象,因此,不管提交多少次都是在执行同一个任务。
这也就是为什么说,需要多少个线程来执行就提交多少次,因为提交的都是同一个任务(任务对象)。
当然,也可以提交多个不同的任务,这样就是多个线程执行多个不同的任务。
2、关于线程池分配任务:
点一:
newCachedThreadPool虽然会根据任务个数来动态的创建线程数,即:提交了5个任务,就应该会创建5个线程。但是,具体哪些线程执行,这是由线程之间自己通过抢占CPU执行权来决定的。
即:线程池只会创建线程并分配任务给线程,但不保证这些线程都会执行,因为任务比较简单的话,就可能很快执行完了(同一个任务前提下)
点二:
往线程池中提交n次任务,不管是同一个任务还是不同的任务,线程池都会分配n个线程(不够就先等待)来执行,但同一任务且任务较简单时,不确保每个线程都会执行到。
提交相同的任务:线程间相互抢占CPU执行权进行执行,直到当前任务执行完;
提交不同的任务:线程间相互抢占CPU执行权进行执行,直到所有任务(或者说每个线程的任务)都执行完。
3、关于线程池的关闭:
shutdown:启动有序关闭,其中先前提交的任务将被执行,但不会接受任何新任务
shutdownNow:尝试停止所有正在执行的任务,停止等待任务的处理,并返回正在等待执行的任务列表。
六、总结
其实线程池的使用挺简单的,关键在于自己要理解。所以,如果一遍没懂的话就多看几遍吧!
Java新手,若有错误,欢迎指正!