大家好,我是Leo!今天准备和大家一起分享的知识是线程池,刚好今天在看八股文,就顺带写一下并把一些实践的例子和大家分享一下…

线程池是什么?

线程池,简单的说就是一个管理线程的池子。

可以帮助管理线程,当我们需要使用线程时,我们可以直接从池子中获取即可,可以降低资源的消耗,因为采用池化技术可以重复利用已建立的线程,可以降低线程创建和销毁造成的损耗。而且可以提高响应速度,当任务到达时,从池子中拿线程,肯定是比你重新创建一条线程快的。

线程池的主要参数

其实在阿里巴巴Java开发手册中是不希望我们采用Executors来创建线程池,更推荐采用ThreadPoolExecutor来创建线程池,因为这样线程池的资源配置由程序员自己决定,可以降低爆内存的风险,ThreadPoolExecutor支持7大参数,分别如下。

  • int corePoolSize:核心线程数

  • int maximumPoolSize:最大线程数

  • long keepAliveTime:非核心线程存活时间

  • TimeUnit unit:非核心线程存活时间单位

  • BlockingQueue workQueue:等待队列

  • ThreadFactory threadFactory:创建线程使用工厂

  • RejectedExecutionHandler handler:线程池拒绝策略

线程池的拒绝策略

线程池常见的有4中拒绝策略:

  • AbortPolicy:直接抛出异常RejectedExecutionException,是默认的处理方法

  • CallerRunsPolicy:由调用线程来处理这个任务

  • DiscardOldestPolicy:丢弃队列最前面的任务,然后尝试执行该任务

  • DiscardPolicy:直接丢弃当前任务

当然除了上述策略,也支持自定义拒绝策略,通过实现RejectedExecutionHandler,重写

rejectedExecution方法既可以自定义拒绝策略。

public class RejectHandler implements RejectedExecutionHandler {

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 自定义拒绝策略
        System.out.println("我是自定义拒绝策略~");

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4T4JPYuc-1677772046314)(C:\Users\DY\AppData\Roaming\marktext\images\2023-03-02-23-27-44-image.png)]

创建线程池的方式

Executors.newCachedThreadPool(),创建一个缓存线程池,内部也是调用了ThreadPoolExecutor,但是它的最大任务数量是Integer.MAX_VALUE,maximumPoolSize也就失效了,在设置了等待200ms时,也可以发现,一直都是一个线程在处理,即可以体现是按需进行创建。

private static ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

    public void test() {
        for (int i = 0; i < 100; i++) {
            int index = i;
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            cachedThreadPool.submit(new Thread(() -> System.out.println(Thread.currentThread().getName() + ":" + index)));
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-18fWKUMX-1677772046315)(C:\Users\DY\AppData\Roaming\marktext\images\2023-03-02-17-36-53-image.png)]

Executors.newSingleThreadExecutor(),这个是创建一个核心线程数为1,最大线程数也为1的线程池,可以看到只有一条线程在处理。

private static ExecutorService singeThreadPool = Executors.newSingleThreadExecutor();
    public void testSingle() {
        for (int i = 0; i < 10; i++) {
            int index = i;

            singeThreadPool.submit(new Thread(() -> System.out.println(Thread.currentThread().getName() + ":" + index)));
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f12dsKzT-1677772046315)(C:\Users\DY\AppData\Roaming\marktext\images\2023-03-02-17-43-40-image.png)]

Executors.newFixedThreadPool(), 可以指定核心线程数和最大线程数,没有所谓的非空闲时间。

private static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
    public void testFixed() {
        for (int i = 0; i < 100; i++) {
            int index = i;
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            fixedThreadPool.submit(new Thread(() -> System.out.println(Thread.currentThread().getName() + ":" + index)));
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TiT7Qd15-1677772046315)(C:\Users\DY\AppData\Roaming\marktext\images\2023-03-02-18-50-08-image.png)]

Executors.newScheduledThreadPool(Runnable command, long delay, TimeUnit uni)

支持延时任务的提交

除此之外,还有一个newSingleThreadScheduledExecutor可以创建支持延时的单线程线程池。

private static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
    public void testScheduled() {
        for (int i = 0; i < 1; i++) {
            int index = i;
            System.out.println("添加时间" + new Date());
            scheduledThreadPool.schedule(new Thread(() ->{
                System.out.println(Thread.currentThread().getName() + ":" + index + "time:" + new Date());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }), 1, TimeUnit.SECONDS);
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-twGTdZRJ-1677772046316)(C:\Users\DY\AppData\Roaming\marktext\images\2023-03-02-19-01-53-image.png)]

关闭线程池

  • shutdown(),关闭线程池,会处理已提交的任务,不会再添加任务

  • shutdownNow(),不会处理已提交任务,也不会再添加新的任务

本文主要介绍了线程池常见的创建方式、7个参数、线程池的拒绝策略以及自定义实现拒绝策略,希望本文内容对你有帮助!!!????????????