什么是线程池
线程池就是创建多个可执行的线程,放到一个容器中,每当有任务需要执行时,就会分配给池中的某个线程,当任务执行结束时,线程不会执行销毁,而是回到池中,等待下一个任务
为什么使用线程池
在某些情况下,我们可能需要大量的创建线程,执行完任务再销毁,频繁的创建和销毁是很浪费资源的,所有我们采用线程池,创建出来的线程并不会销毁,而是回到池中,当有任务时,直接从池子中拿,不再创建
创建线程池的两种方式
1、new ThreadPoolExecutor()
构造方法:public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) ;
参数意义
/**
* corePoolSize:线程池中常驻核心线程数
* maximumPoolSize:线程池能够容纳同时执行的最大线程数,当任务队列满了,会继续创建新的线程,直到达到此值
* keepAliveTime:多余的空闲线程存活时间。当前线程池数量超过corePoolSize时,当空闲时间到达keepAliveTime值时,多余空闲线程会被销毁直到只剩下corePoolSize个线程为止。
* unit:keepAliveTime的时间单位
* workQueue:任务队列,被提交但尚未执行的任务
* 1.直接提交队列(SynchronousQueue): 设置为SynchronousQueue队列,SynchronousQueue是一个特殊的BlockingQueue,
* 使用SynchronousQueue阻塞队列一般要求maximumPoolSizes为无界(Integer.MAX_VALUE),避免线程拒绝执行操作。
* 它没有容量,每执行一个插入操作就会阻塞,需要再执行一个删除操作才会被唤醒,
* 反之每一个删除操作也都要等待对应的插入操作。
*
* 2.有界任务队列(ArrayBlockingQueue):使用ArrayBlockingQueue有界任务队列,若有新的任务需要执行时,
* 线程池会创建新的线程,直到创建的线程数量达到corePoolSize时,
* 则会将新的任务加入到等待队列中。若等待队列已满,
* 即超过ArrayBlockingQueue初始化的容量,则继续创建线程,
* 直到线程数量达到maximumPoolSize设置的最大线程数量,若大于maximumPoolSize,则执行拒绝策略
*
* 3.无界任务队列(LinkedBlockingQueue):使用无界任务队列,线程池的任务队列可以无限制的添加新的任务,
* 而线程池创建的最大线程数量就是你corePoolSize设置的数量,
* 也就是说在这种情况下maximumPoolSize这个参数是无效的,
* 哪怕你的任务队列中缓存了很多未执行的任务,当线程池的线程数达到corePoolSize后,
* 就不会再增加了;若后续有新的任务加入,则直接进入队列等待
*
* 4.优先任务队列(PriorityBlockingQueue): 除了第一个任务直接创建线程执行外,其他的任务都被放入了优先任务队列,
* 线程需要实现Comparable接口,并重写方法
* 按优先级进行了重新排列执行,且线程池的线程数一直为corePoolSize,也就是只有一个
*
* threadFactory:表示生成线程池中的工作线程的线程工厂,用于创建线程,一般为默认线程工厂即可
*
* handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时如何来拒绝来请求的Runnable的策略
* 1、AbortPolicy策略:该策略会直接抛出异常,阻止系统正常工作,也就是主线程不会继续执行下去,已经开启的子线程仍会执行;
* 2、CallerRunsPolicy策略:如果线程池的线程数量达到上限,该策略会把任务队列中的任务放在调用者线程当中运行;
* 3、DiscardOldestPolicy策略:该策略会丢弃任务队列中最老的一个任务,也就是当前任务队列中最先被添加进去的,马上要被执行的那个任务,并尝试再次提交;
* 4、DiscardPolicy策略:该策略会默默丢弃无法处理的任务,不予任何处理。当然使用此策略,业务场景中需允许任务的丢失;
*/
2、Executors工厂方法创建
- Executors.newSingleThreadExecutor():创建当单个线程的线程池,如果这个线程出现异常终止,会有其他线程代替他,好处是保证了顺序执行各个任务
- Executors.newFixedThreadPool(3) :创建固定数量线程的线程池,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
- Executors.newCachedThreadPool():创建一个会根据需要创建新线程的线程池,也就是有空闲线程就不用创建新的线程,没有就创建新的线程
1、工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
2、如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
3、在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。 - Executors.newScheduledThreadPool(2):创建拥有固定线程数量的定时线程任务的线程池,延迟执行
ScheduledExecutorService es3 = Executors.newScheduledThreadPool(2);
MyThread1 myThread1 = new MyThread1();
// 参数的含义依次为:执行线程、初始化延时、线程调用时间间隔、计时单位
es3.scheduleAtFixedRate(myThread1,10,10, TimeUnit.SECONDS);
- Executors.newSingleThreadScheduledExecutor():创建只有一个线程的定时线程任务的线程池,延迟执行