【线程】ThreadPool 线程池 Executors 实战 (十九)

我的原则:先会用再说,内部慢慢来。
学以致用,根据场景学源码


一、工具类 Executors

1.1 UML 图

在这里插入图片描述

1.2 四个常用方法
方法描述
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 (线程可复用)
newFixedThreadPool创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
1.3 线程池的作用
  1. 提供了一个线程队列,队列中保存着所有等待状态的线程。避免了创建与销毁额外开销,提高了相应速度。

=== 点击查看top目录 ===

二、实战

2.1 newCachedThreadPool 方法
  • java.util.concurrent.Executors#newCachedThreadPool() 方法,内部线程数量默认 Integer.MAX_VALUE ,线程池为无限大。
  • newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  • 当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
    public static void method_newCachedThreadPool() {
        // 1、创建线程池
        ExecutorService pool = Executors.newCachedThreadPool();
        // 2、分配任务
        for (int i = 0; i < 20; i++) {
            final int index = i;
            pool.execute(() -> {
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "-" + index);
                    }
            );
        }
        // 3、关闭线程池
        pool.shutdown();
    }

输出:

pool-1-thread-2-1
pool-1-thread-9-8
pool-1-thread-10-9
pool-1-thread-1-0
pool-1-thread-12-11
pool-1-thread-14-13
pool-1-thread-15-14
pool-1-thread-17-16
pool-1-thread-18-17
pool-1-thread-19-18
pool-1-thread-20-19
pool-1-thread-8-7
pool-1-thread-13-12
pool-1-thread-6-5
pool-1-thread-7-6
pool-1-thread-3-2
pool-1-thread-5-4
pool-1-thread-16-15
pool-1-thread-4-3
pool-1-thread-11-10

=== 点击查看top目录 ===

2.2 newFixedThreadPool 方法
  • java.util.concurrent.Executors#newFixedThreadPool(int)
  • newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
    public static void method_newFixedThreadPool() {
        // 1、创建线程池
        ExecutorService pool = Executors.newFixedThreadPool(4);

        // 2、分配任务
        for (int i = 0; i < 10; i++) {
            final int index = i;
            pool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + "-" + index);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        // 3、关闭线程池
        pool.shutdown();
    }
  • 因为线程池大小为4,每个任务输出index后sleep 2秒,所以每两秒打印4个数字。
  • 输出:
pool-1-thread-1-0
pool-1-thread-2-1
pool-1-thread-3-2
pool-1-thread-4-3
pool-1-thread-3-4
pool-1-thread-1-7
pool-1-thread-2-6
pool-1-thread-4-5

=== 点击查看top目录 ===

2.3 newScheduledThreadPool 方法
  • java.util.concurrent.Executors#newScheduledThreadPool(int) 规定池内线程最大数量

  • newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

    public static void newScheduledThreadPoolSchedule() {
        // 1、创建线程池
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);

        // 2、分配任务
        // 启动了两个定时的任务,在JVM开启后的1分钟后,每隔2分钟,开始执行一次。
        LoopCount loopCount = new LoopCount();

        for (int i = 0; i < 2; i++) {
            final int index = i;
            pool.scheduleAtFixedRate(() -> System.out.println(Thread.currentThread().getName() + "-" + index + "_count_" + loopCount.getCount().incrementAndGet()),
                    1, 2, TimeUnit.SECONDS);
        }
    }
    @Data
    static class LoopCount{
        private AtomicInteger count = new AtomicInteger(0);
    }

  • 定时及周期性任务操作 scheduleAtFixedRate
  • java.util.concurrent.ScheduledExecutorService#scheduleAtFixedRate 方法
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit)
  • 启动了两个定时的任务,在JVM开启后的1分钟后,每隔2分钟,开始执行一次。
  • 输出:
pool-1-thread-1-0_count_1
pool-1-thread-2-1_count_2
pool-1-thread-2-0_count_3
pool-1-thread-1-1_count_4
pool-1-thread-3-0_count_5
pool-1-thread-2-1_count_6
pool-1-thread-3-0_count_7
pool-1-thread-1-1_count_8
pool-1-thread-2-0_count_9
pool-1-thread-3-1_count_10
pool-1-thread-1-0_count_11
pool-1-thread-1-1_count_12
pool-1-thread-1-0_count_13

=== 点击查看top目录 ===

2.4 newSingleThreadExecutor 方法
  • java.util.concurrent.Executors#newSingleThreadExecutor()
  • 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
    public static void method_newSingleThreadExecutor() {
        // 1、创建线程池
        ExecutorService pool = Executors.newSingleThreadExecutor();
        // 2、分配任务
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            final int index = i;
            pool.execute(() -> System.out.println(Thread.currentThread().getName() + "-" + index));
        }
        // 3、关闭线程池
        pool.shutdown();
    }

输出:

pool-1-thread-1-0
pool-1-thread-1-1
pool-1-thread-1-2
pool-1-thread-1-3
pool-1-thread-1-4
pool-1-thread-1-5
pool-1-thread-1-6
pool-1-thread-1-7
pool-1-thread-1-8
pool-1-thread-1-9

三、番外篇

下一章节:【线程】ThreadPool 线程池底层剖析 (二十)
上一章节:【线程】Thread.UncaughtExceptionHandler 实战与剖析 (十八)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值