Java 如何创建线程池
通过Executors类提供的方法
1、newCachedThreadPool:创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程
2、newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待
3、newScheduledThreadPool:创建一个周期性的线程池,支持定时及周期性执行任务
4、newSingleThreadExecutor:创建一个单线程的线程池,可保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
通过ThreadPoolExecutor类自定义
7个参数如下:
(1)corePoolSize:核心线程数,线程池中始终存活的线程数。
(2)maximumPoolSize: 最大线程数,线程池中允许的最大线程数。
(3)keepAliveTime: 存活时间,线程没有任务执行时最多保持多久时间会终止。
(4)unit: 单位,参数keepAliveTime的时间单位,7种可选。
(5)workQueue: 一个阻塞队列,用来存储等待执行的任务,均为线程安全,7种可选。
(6)threadFactory: 线程工厂,主要用来创建线程,默及正常优先级、非守护线程。
(7)handler:拒绝策略,拒绝处理任务时的策略,4种可选,默认为AbortPolicy。
线程池的执行规则:
(1)当线程数小于核心线程数时,创建线程;
(2)当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
(3)当线程数大于等于核心线程数,且任务队列已满:
- (3.1)若线程数小于最大线程数,创建线程;
- (3.2)若线程数等于最大线程数,抛出异常,拒绝任务;
线程池的优点
1、减少创建和销毁线程的次数,每个工作线程都可以被重复利用,可以执行多个任务;
2、防止因为线程过多消从而耗过多的内存,导致死机;可以根据系统的承受能力,调整线程池中工作线程的数目,(每个线程需要约1MB的内存,线程开的越多,消耗的内存也就越大,最后死机)
线程复用,线程对象被反复使用
核心原理
线程池对Thread进行了封装,并不是每次执行任务都会调用Thread.start()来创建新线程,而是让每个线程去执行一个”循环任务“,在这个循环任务里,不停的检查是否还有任务等待被执行,如果有则直接去执行这个任务,也就是调用任务的run()方法,把run()当作普通方法直接调用,而不是创建一个新线程来执行run()方法,所以线程数量并不增加
拒接策略
1、AbortPolicy:直接抛出异常,阻止线程正常运行
2、CallerRunsPolicy:如果被丢弃的线程任务未关闭,则执行该线程任务
3、DiscardOldestPolicy:移除任务队列中最早的一个线程任务,并尝试提交当前任务
4、DiscardPolicy:丢弃当前的线程任务而不做任何处理
5、自定义拒绝策略:可实现RejectedExecutionHandler接口老实现拒绝策略,并捕获异常来实现自定义拒绝策略