Java - 并发编程 - 线程池(图解)

以你之姓@ 2023-07-07 11:17 77阅读 0赞

前言

做的学习笔记,并加入了自己的理解,谢谢

使用线程池的原因

我们创建的线程在运行结束后都会被虚拟机销毁,如果线程数量多的话,频繁的创建和销毁线程会大大浪费时间和效率,更重要的是浪费内存,线程池可以让线程运行后不立刻销毁,而是让线程重复使用,继续执行其他任务

线程池的优化

  1. 降低资源消耗
  2. 提高响应速度
  3. 提高线程的可管理性

流程图

img

线程池的核心参数

  1. /** * 线程核心参数 * @param corePoolSize 核心线程数量 * @param maximumPoolSize 最大线程数量 * @param keepAliveTime 线程空间后的存活时间 * @param unit 时间单位 * @param workQueue 用于存放任务的阻塞队列 * @param threadFactory 线程工厂类 * @param handler 当队列和最大线程池都满了之后的饱和策略 */
  2. public ThreadPoolExecutor(int corePoolSize,
  3. int maximumPoolSize,
  4. long keepAliveTime,
  5. TimeUnit unit,
  6. BlockingQueue<Runnable> workQueue,
  7. ThreadFactory threadFactory,
  8. RejectedExecutionHandler handler)

线程池可选择的阻塞队列

  • 无界队列
  • 有界队列 如果超出界定值,将阻塞 put 方法
  • 同步移交队列 也就是队列不存储元素,每个插入操作都要等待另一个线程调用移出操作,否则插入操作一直处于阻塞

无界队列

  1. ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>();
  2. for (int i = 0; i < 10; i++) {
  3. queue.put(i);
  4. System.out.println("向队列中添加值:" + i);
  5. }
  6. LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
  7. for (int i = 0; i < 10; i++) {
  8. queue.put(i);
  9. System.out.println("向队列中添加值:" + i);
  10. }

有界队列

  1. ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);
  2. for (int i = 0; i < 10; i++) {
  3. queue.put(i);
  4. System.out.println("向队列中添加值:" + i);
  5. }
  6. LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(5);
  7. for (int i = 0; i < 10; i++) {
  8. queue.put(i);
  9. System.out.println("向队列中添加值:" + i);
  10. }

同步移交队列

  1. SynchronousQueue<Integer> queue = new SynchronousQueue<>();
  2. for (int i = 0; i < 10; i++) {
  3. // 阻塞在这里
  4. queue.put(i);
  5. System.out.println("向队列中添加值:" + i);
  6. }
  7. SynchronousQueue<Integer> queue = new SynchronousQueue<>();
  8. // 插入值
  9. new Thread(() -> {
  10. try {
  11. queue.put(1);
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. }).start();
  16. // 取值
  17. new Thread(() -> {
  18. try {
  19. Integer value = queue.take();
  20. System.out.println("取到值:" + value);
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. }
  24. }).start();

线程池可选择的饱和策略


























说明
AbortPolicy 丢弃任务并抛出RejectedExecutionException异常 《默认》
DiscardPolicy 抛弃策略,但是不抛出异常
DiscardOldestPolicy 丢弃队列最前面的任务(旧任务),然后重新尝试执行任务
CallerRunsPolicy 由调用线程处理该任务

常用线程池

线程数量无限的线程池

  1. ExecutorService pool = Executors.newCachedThreadPool();
  2. public class Executors {
  3. public static ExecutorService newCachedThreadPool() {
  4. return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
  5. 60L, TimeUnit.SECONDS,
  6. new SynchronousQueue<Runnable>());
  7. }
  8. }

线程数量固定线程池

  1. ExecutorService pool = Executors.newFixedThreadPool(5);
  2. public static ExecutorService newFixedThreadPool(int nThreads) {
  3. return new ThreadPoolExecutor(nThreads, nThreads,
  4. 0L, TimeUnit.MILLISECONDS,
  5. new LinkedBlockingQueue<Runnable>());
  6. }

单一线程线程池

  1. ExecutorService pool = Executors.newSingleThreadExecutor();
  2. public static ExecutorService newSingleThreadExecutor() {
  3. return new FinalizableDelegatedExecutorService
  4. (new ThreadPoolExecutor(1, 1,
  5. 0L, TimeUnit.MILLISECONDS,
  6. new LinkedBlockingQueue<Runnable>()));
  7. }

提交任务

submit,获取结果

  1. ExecutorService threadPool = Executors.newCachedThreadPool();
  2. // 提交任务,并获取结构
  3. Future<Integer> future = threadPool.submit(() -> {
  4. Thread.sleep(3000L);
  5. return 2 * 5;
  6. });
  7. // 阻塞获取结果
  8. Integer value = future.get();
  9. System.out.println("执行结果:" + value);

execute,没有结果

  1. ExecutorService threadPool = Executors.newCachedThreadPool();
  2. threadPool.execute(() -> {
  3. try {
  4. Thread.sleep(1000L);
  5. } catch (InterruptedException e) {
  6. e.printStackTrace();
  7. }
  8. // 计算结果
  9. Integer num = 2 * 3;
  10. System.out.println("执行结果:" + num);
  11. });

线程池的状态

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,77人围观)

还没有评论,来说两句吧...

相关阅读

    相关 并发编程-线

    文章目录 线程池 线程池原理 线程池分类 线程池 为什么需要使用线程池? 线程的创建和销毁都需要消耗系统资源,线程池可以复

    相关 Java并发编程:(5)线

    思考这样一个问题: 如果并发线程数量多,且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。那么有没有一

    相关 Java并发编程学习——线

           如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。