当前位置:   article > 正文

java线程池(简单易懂)

java线程池

 1 .线程池主要核心原理和优势

   1.1线程池核心原理

  1. 创建一个池子,池子当中是空的
  2. 提交任务时,池子会创建新的线程对象,任务执行完毕,线程会归还给池子,下次再次提交任务时,不需要创建新的线程,直接复用已有的线程即可。
  3. 如果提交任务时,池子中没有空闲线程,也无法创建新的线程,队伍就会排队等待。

 1.2线程池主要优势

  1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  2. 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
  3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

2. 线程池的代码实现

2.1通过Executors线程池工具类通过调用方法创建不同类型的线程池对象。

  1. //代码实现
  2. /**
  3. * 创建一个没有上限的线程池
  4. */
  5. ExecutorService executorService = Executors.newCachedThreadPool();
  6. /**
  7. * 往线程池中提交任务
  8. */
  9. LoopTread loopTread = new LoopTread();
  10. executorService.submit(loopTread);
  11. executorService.submit(loopTread);
  12. executorService.submit(loopTread);
  13. executorService.submit(loopTread);
  14. /**
  15. * 销毁线程池
  16. * 此方法一般不用,因为线程池一般在项目中不进行销毁,随时会有任务
  17. */
  18. executorService.shutdown();
  19. /**
  20. * 创建一个有上限的线程池
  21. * 3代表这个线程最多只能同时有三个线程
  22. */
  23. ExecutorService executorService1 = Executors.newFixedThreadPool(3);
  24. /**
  25. * 提交任务
  26. * 提交五个任务,从控制台输出可以看出线程的复用
  27. */
  28. executorService1.submit(loopTread);
  29. executorService1.submit(loopTread);
  30. executorService1.submit(loopTread);
  31. executorService1.submit(loopTread);
  32. executorService1.submit(loopTread);

 一共五个任务,但确只使用了三个线程,这就是线程池里的代码复用。

2.2自定义创建线程池(创建ThreadPoolExecutor类)

它最长的构造方法有七个参数。

  1. 核心线程数量——在线程池当中无论空闲多久都不会被删除的线程
  2. 线程池当中最大的线程数量——线程池当中最大能创建的线程数量
  3. 空闲时间(数值)——临时线程(线程池中出核心线程之外的线程)空闲了多久就会被淘汰的时间。
  4. 空闲时间(单位)——临时线程空闲了多久就会被淘汰的时间单位,要用枚举类TimeUnit类作为参数
  5. 阻塞队列——就是创建一个阻塞队列作为参数传入,就是当线程池当中线程数量已经达到了最大线程数量,允许多少个任务排队获取线程,其余的用参数七那个方案来处理。
  6. 创建线程的方式——不是new一个线程,而是传入一个线程工厂(例如:Executors工具类中的defaultThreadFactory方法返回的就是一个线程工厂)
  7. 要执行的任务过多时的解决方案——当等待队列中也排满时要怎么处理这些任务(任务拒绝策略)。

  1. //代码实现
  2. /**
  3. * 之前用工具类进行创建,有好多参数不能自己设置
  4. * 咱直接自己手动创建一个线程池,自己设置参数
  5. * 参数一:核心线程数量 不能小于0
  6. * 参数二:最大线程数 不能小于0,数值大于等于核心线程数量
  7. * 参数三:空闲临时线程最大存活时间(数值) 不能小于0
  8. * 参数四:空闲临时线程最大存活时间(单位) 用TimeUnit这个枚举类表示
  9. * 参数五:任务队列,也就是一个堵塞队列 不能为null
  10. * 参数六:创建线程的工厂 不能为null
  11. * 参数七:任务的拒绝策略 不能为null
  12. */
  13. ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
  14. 3, // 核心线程数量
  15. 6, //最大线程数
  16. 60, //空闲临时线程最大存活时间(数值)
  17. TimeUnit.SECONDS,//空闲临时线程最大存活时间(单位)
  18. new ArrayBlockingQueue<>(3),//任务队列,也就是一个堵塞队列,也可以使用LinkedBlockingQueue这个阻塞队列
  19. Executors.defaultThreadFactory(),//用线程池工具类Executors创建线程的工厂
  20. new ThreadPoolExecutor.AbortPolicy()//任务的拒绝策略中其中一个,丢弃任务并抛出RejectedExecutionException
  21. );
  22. threadPoolExecutor.submit(loopTread);
  23. threadPoolExecutor.submit(loopTread);
  24. threadPoolExecutor.submit(loopTread);
  25. threadPoolExecutor.submit(loopTread);
  26. threadPoolExecutor.submit(loopTread);
  27. threadPoolExecutor.submit(loopTread);
  28. threadPoolExecutor.submit(loopTread);
  29. threadPoolExecutor.submit(loopTread);
  30. threadPoolExecutor.submit(loopTread);
  31. threadPoolExecutor.submit(loopTread);
  32. threadPoolExecutor.submit(loopTread);
  33. threadPoolExecutor.submit(loopTread);
  34. threadPoolExecutor.submit(loopTread);
  35. threadPoolExecutor.submit(loopTread);
  36. threadPoolExecutor.submit(loopTread);
  37. threadPoolExecutor.submit(loopTread);
  38. threadPoolExecutor.submit(loopTread);
  39. threadPoolExecutor.submit(loopTread);
  40. }

上面的代码我们设置最大线程数量为6,而阻塞队列可以排三个,说明当同时有超过9个任务需要执行,第10个线程就会执行拒绝策略,我设置的策略为丢弃任务,并抛出异常RejectedExecutionException。下面有结果就可以证明我们的猜测。

 74行恰好是我们放入线程池中第10个任务,所以第74行抛出了RejectedExecutionException异常。

自定义线程在不断的提交任务时有三个临界点:

  • 当核心线程满时,再提交队伍就会在阻塞队列中排队
  • 当核心线程满了,阻塞队列中也满了,才会创建临时线程
  • 当核心线程满了,阻塞队列满了,临时线程也满了,会触发任务拒绝策略,也就是参数七

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/498843
推荐阅读
相关标签
  

闽ICP备14008679号