【Executors】线程池的4种常见创建方式

这世界上没有优秀的理念,只有脚踏实地的结果 。 

一、 创建缓存型线程池(CachedThreadPool)

1、定义:

          Executors.newCacheThreadPool():可缓存线程池,先查看线程池中有没有之前创建的线程,如果有则直接使用。否则就新创建一个新的线程加入线程池中,我们经常用此类线程池来执行一些业务处理时间很短的任务。

2、示例代码:

情况1:

public static void main(String[] args) {
        //创建一个可缓存的线程池
        ExecutorService executorService = Executors.newCachedThreadPool();
        //循环创建10个线程
        for (int i = 0; i < 10; i++) {
            try {
                //模拟线程调用间隔时间
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            executorService.submit(() -> {
                try {
                    //模拟业务处理时间
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("使用 newCachedThreadPool-->创建线程:"+Thread.currentThread().getName());
            });
        }
    }

执行结果:

使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1

情况2:我们将模拟业务执行时间改大一点:10ms->1000ms,再次执行结果如下:

使用 newCachedThreadPool-->创建线程:pool-2-thread-1
使用 newCachedThreadPool-->创建线程:pool-2-thread-2
使用 newCachedThreadPool-->创建线程:pool-2-thread-3
使用 newCachedThreadPool-->创建线程:pool-2-thread-4
使用 newCachedThreadPool-->创建线程:pool-2-thread-5
使用 newCachedThreadPool-->创建线程:pool-2-thread-6
使用 newCachedThreadPool-->创建线程:pool-2-thread-7
使用 newCachedThreadPool-->创建线程:pool-2-thread-8
使用 newCachedThreadPool-->创建线程:pool-2-thread-9
使用 newCachedThreadPool-->创建线程:pool-2-thread-10

从上面代码我们就能看出来缓存型线程池的特性。

二、创建固定长度线程池(FixedThreadPool)

1、定义:

          Executors.newFixedThreadPool():创建一个固定(指定)长度可重用的线程池,可以控制最大创建数,超过最大长度之后就会放入到队列进行等待。

2、示例代码:

 public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            executorService.submit(() -> {
                try {
                    //模拟业务处理时间
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("使用 newFixedThreadPool-->创建线程:"+Thread.currentThread().getName());
            });
        }
    }

执行结果:

使用 newFixedThreadPool-->创建线程:pool-1-thread-1
使用 newFixedThreadPool-->创建线程:pool-1-thread-2
使用 newFixedThreadPool-->创建线程:pool-1-thread-3
使用 newFixedThreadPool-->创建线程:pool-1-thread-4
使用 newFixedThreadPool-->创建线程:pool-1-thread-5
使用 newFixedThreadPool-->创建线程:pool-1-thread-6
使用 newFixedThreadPool-->创建线程:pool-1-thread-7
使用 newFixedThreadPool-->创建线程:pool-1-thread-8
使用 newFixedThreadPool-->创建线程:pool-1-thread-9
使用 newFixedThreadPool-->创建线程:pool-1-thread-10
等待3秒钟。。。。。。。
使用 newFixedThreadPool-->创建线程:pool-1-thread-1
使用 newFixedThreadPool-->创建线程:pool-1-thread-2
使用 newFixedThreadPool-->创建线程:pool-1-thread-3
使用 newFixedThreadPool-->创建线程:pool-1-thread-4
使用 newFixedThreadPool-->创建线程:pool-1-thread-5
使用 newFixedThreadPool-->创建线程:pool-1-thread-6
使用 newFixedThreadPool-->创建线程:pool-1-thread-7
使用 newFixedThreadPool-->创建线程:pool-1-thread-8
使用 newFixedThreadPool-->创建线程:pool-1-thread-9
使用 newFixedThreadPool-->创建线程:pool-1-thread-10
等待3秒钟。。。。。。。
使用 newFixedThreadPool-->创建线程:pool-1-thread-1
使用 newFixedThreadPool-->创建线程:pool-1-thread-2
一直到循环100次。。。。


我们创建了一个固定长度为10的线程池,循环100次创建线程,但是我们发现创建的线程数一直没有超过10,这就是定长线程池,此时后面的90个操作都将放到队列等待,等待前面的10个线程执行完毕后,队列里面的才可以继续去创建。

三、创建可定时执行的线程池(ScheduledThreadPool)

1、定义:

          Executors.newScheduledThreadPool():创建一个支持定时或周期性的执行任务线程池,可以延时执行,可以用做执行定时任务的线程池。

2、代码示例:

public static void main(String[] args) {
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);
        // 参数的含义依次为:执行线程、初始化延时、线程调用时间间隔、计时单位
        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程--->" + Thread.currentThread().getName() + " --->在" + dateFormat.format(new Date()) + "--->执行了此方法。。。");
            }
        }, 5, 10, TimeUnit.SECONDS);
    }

执行结果:

线程--->pool-1-thread-1 --->在2021-04-26 05:21:30--->执行了此方法。。。
线程--->pool-1-thread-1 --->在2021-04-26 05:21:40--->执行了此方法。。。
线程--->pool-1-thread-2 --->在2021-04-26 05:21:50--->执行了此方法。。。
线程--->pool-1-thread-1 --->在2021-04-26 05:22:00--->执行了此方法。。。
线程--->pool-1-thread-3 --->在2021-04-26 05:22:10--->执行了此方法。。。
线程--->pool-1-thread-2 --->在2021-04-26 05:22:20--->执行了此方法。。。
线程--->pool-1-thread-4 --->在2021-04-26 05:22:30--->执行了此方法。。。
线程--->pool-1-thread-1 --->在2021-04-26 05:22:40--->执行了此方法。。。
线程--->pool-1-thread-5 --->在2021-04-26 05:22:50--->执行了此方法。。。

启动程序后,第一次执行方法需要等待5s,后续每10s执行一次。

四、创建单线程化线程池(SingleThreadExecutor)

1、定义:

          Executors.newSingleThreadExecutor():创建一个单线程化线程池,它只能用一个工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

2、示例代码:

  public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int number = i;
            executorService.submit(() -> {
                System.out.println("当前执行编号:" + number);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

    }

执行结果:

当前执行编号:0
当前执行编号:1
当前执行编号:2
当前执行编号:3
当前执行编号:4
当前执行编号:5
当前执行编号:6
当前执行编号:7
当前执行编号:8
当前执行编号:9

执行代码会看到同一时间只有一个线程执行,其余的任务都会有序等待且有序的执行。

你可能感兴趣的:(JAVA,线程池,多线程,java,队列)