一.环境
idea
二.什么是多线程,使用多线程有什么好处
有过数据库基础的应该了解过数据库连接池:作用是用来管理数据库连接
线程池的作用与数据库连接池作用相同:是用来管理线程的
2.1好处
第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。
三.多线程的几种创建方式
在从jdk1.5以后,jdk为我们提供了并发包中的Executors来创建线程池
3.1newCachedThreadPool(可缓存的线程池)
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); for (int i=0;i<10;i++){//创建10个线程 final int temp=i; executorService.execute(new Runnable() { public void run() {//线程调度的业务代码 System.out.println(Thread.currentThread().getName()+",i:"+temp); } }); } executorService.shutdown();//关闭线程池 }
由运行结果可以看出虽然使用代码创建了10个线程,但是实际却只创建了9个,说明有线程被复用了。翻看源码后。。。。
打开ThreadPoolExecutor()方法发现,
int corePoolSize,//创建线程池的核心线程数
int maximumPoolSize,//创建线程池的最大线程数
long keepAliveTime,//等待时间
TimeUnit unit,//单位
BlockingQueue<Runnable> workQueue//底层使用阻塞队列存储
可以知道可缓存的线程池是没有创建核心线程池的,最大线程数等于int的最大值
3.2 newFixedThreadPool (定长的线程池)
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(3); for (int i=0;i<10;i++){//创建10个线程 final int temp=i; executorService.execute(new Runnable() { public void run() {//线程调度的业务代码 System.out.println(Thread.currentThread().getName()+",i:"+temp); } }); } executorService.shutdown();//关闭线程池 }
由结果显示线程只有三个,那么是否就证明定长线程池就创建指定长度的线程数呢!!!!!查看源码
发现源码调用了ThreadPoolExecutor()方法并将入参传递了下去
所以可以得出结论定长线程池的线程池数量是固定的。
3.3 newFixedThreadPool (可定时的线程池)
创建一个定长线程池,支持定时及周期性任务执行
public static void main(String[] args) { ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3); for (int i=0;i<10;i++){//创建10个线程 final int temp=i; scheduledExecutorService.schedule(new Runnable() { public void run() {//线程调度的业务代码 System.out.println(Thread.currentThread().getName()+",i:"+temp); } },3, TimeUnit.SECONDS); } scheduledExecutorService.shutdown();//关闭线程池 }
该效果是当程序运行了3秒后才调用。由于运行效果和定长差不多。所以看一下源码是不是也是只创建了3个线程。
所以可以看出可定时的线程长度并不是指定长度,而是Int的最大值
3.3 newSingleThreadExecutor (单线程的线程池)
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
public static void main(String[] args) { ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); for (int i=0;i<10;i++){//创建10个线程 final int temp=i; scheduledExecutorService.execute(new Runnable() { public void run() {//线程调度的业务代码 System.out.println(Thread.currentThread().getName()+",i:"+temp); } }); } scheduledExecutorService.shutdown();//关闭线程池 }
同上,翻看源码
由源码可知单线程的线程池只创建一个线程