JavaEE 初阶篇-深入了解线程池(线程池创建、线程池如何处理任务)

🔥博客主页: 【小扳_-CSDN博客】**
❤感谢大家点赞👍收藏⭐评论✍**

文章目录

[1.0 线程池概述](#1.0 线程池概述)

[1.1 线程池的优点](#1.1 线程池的优点)

[1.2 不使用线程池的问题](#1.2 不使用线程池的问题)

[1.3 线程池的工作原理图](#1.3 线程池的工作原理图)

[1.4 如何创建线程池?](#1.4 如何创建线程池?)

[2.0 通过 ThreadPoolExecutor 类自定义创建线程池](#2.0 通过 ThreadPoolExecutor 类自定义创建线程池)

[2.1 ThreadPoolExecutor 构造器](#2.1 ThreadPoolExecutor 构造器)

[3.0 线程池处理 Runnable 任务](#3.0 线程池处理 Runnable 任务)

[3.1 通过 void execute(Runnable command) 方法](#3.1 通过 void execute(Runnable command) 方法)

[3.2 通过 void shutdown() 方法](#3.2 通过 void shutdown() 方法)

[3.3 通过 List](#3.3 通过 List) [shutdownNow() 方法](#shutdownNow() 方法)

[3.4 临时线程什么时候创建?](#3.4 临时线程什么时候创建?)

[3.5 什么时候会开始拒绝新任务?](#3.5 什么时候会开始拒绝新任务?)

[4.0 线程池处理 Callable 任务](#4.0 线程池处理 Callable 任务)

[4.1 通过 submit() 方法](#4.1 通过 submit() 方法)

[5.0 通过 Executors 工具类创建出线程池](#5.0 通过 Executors 工具类创建出线程池)

[5.1 通过 Executors.newFixedThreadPool(int nThreads) 方法来创建线程池](#5.1 通过 Executors.newFixedThreadPool(int nThreads) 方法来创建线程池)

[5.2 通过 Executors.newCachedThreadPool() 方法来创建线程池](#5.2 通过 Executors.newCachedThreadPool() 方法来创建线程池)

[5.3 通过 Eexcutors.newSingleThreadExecutor() 方法来创建线程池](#5.3 通过 Eexcutors.newSingleThreadExecutor() 方法来创建线程池)

[6.0 新任务拒绝策略](#6.0 新任务拒绝策略)

[6.1 AbortPolicy(默认策略,直接抛出异常)](#6.1 AbortPolicy(默认策略,直接抛出异常))

[6.2 DiscardPolicy(直接丢弃任务)](#6.2 DiscardPolicy(直接丢弃任务))

[6.3 CallerRunsPolicy(由调用线程执行任务)](#6.3 CallerRunsPolicy(由调用线程执行任务))

[6.4 DiscardOldestPolicy(丢弃队列中最旧的任务)](#6.4 DiscardOldestPolicy(丢弃队列中最旧的任务))


1.0 线程池概述

线程池是一种重要的并发编程机制,用于管理和复用线程,以提高应用程序的性能和资源利用率。

线程池就是一个可以复用线程的技术。

简单来说,线程池起到了复用线程的作用。假如不用线程池的话,用线程来处理任务,来多少任务就要创建多少了线程,这就会导致线程堆积,而且线程的创建和销毁虽然比进程的消耗低,但是对于大量的线程进行创建和销毁,就会导致消耗更大了,这里的消耗主要是指 CPU 消耗。还有一方面的原因,如果手动创建线程的话,需要通过内核进行创建;若在线程池中取出线程,不需要通过内核,直接通过用户态即可。所以总结来说,线程池中的线程一次创建完毕之后,不执行任务的时候,核心线程就存放在线程池中,临时线程会有一个时间的存放,超过了规定的时间就会自动销毁;需要执行任务的时候,就会从线程池中取出线程,此时不需要通过内核态,直接是通过用户态。用完之后,将线程放回到线程池中,等待下一个任务。

1.1 线程池的优点

1)降低线程创建和销毁的开销。通过重用线程从而减少频繁创建和开销线程所带来的性能损耗。

2)控制并发线程数量。通过设定线程池的大小和配置,可以限制并发线程的数量,避免系统资源耗尽。

1.2 不使用线程池的问题

假设用户发起一个请求,后台就需要创建一个新线程来处理,下次新任务来了肯定又要创建新线程处理的,而创建新线程的开销是很大的,并且请求过多时,肯定会产生大量的线程出来,这样会严重影响系统的性能。

1.3 线程池的工作原理图

1.4 如何创建线程池?

常见的创建线程池的方式有两种:

1)通过已经实现 ExecutorService 接口的 ThreadPoolExecutor 类来创建出线程池。

2)通过 Executors 工具类创建出线程池。

2.0 通过 ThreadPoolExecutor 类自定义创建线程池

可以直接使用 ThreadPoolExecutor 类来创建自定义的线程池,通过指定核心线程数、最大线程数、工作队列等参数来满足特定的需求。这种方法更灵活,可以根据具体场景进行定制化配置。

2.1 ThreadPoolExecutor 构造器

1)参数一:corePoolSize:指定线程池的核心线程的数量。

2)参数二:maximumPoolSize:指定线程池的最大线程数量。

3)参数三:keepAliveTime:指定临时线程的存活时间。

4)参数四:unit:指定临时线程的存活时间单位(秒、分、时、天)。

5)参数五:workQueue:指定线程池的任务队列。

6)参数六:threadFactory:指定线程池的线程工厂(创建线程的地方)。

7)参数七:handler:指定线程池的任务拒绝策略(线程都在忙,任务队列也满的时候,新任务来了该怎么处理)。

具体创建线程池代码如下:

java 复制代码
import java.util.concurrent.*;
public class CreateThreadPoolExecutor {

    public Executor threadPool = new ThreadPoolExecutor(
            3,//核心线程数量
            5,//最大线程数量
            8,//临时线程存活时间
            TimeUnit.SECONDS,//临时线程存活时间单位
            new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4
            Executors.defaultThreadFactory(),//线程工厂,
            //用到了Executors工具类来创建默认线程工厂
            new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略:抛出异常
    
}

3.0 线程池处理 Runnable 任务

线程池通过执行 Runnable 任务来实现多线程处理。将实现 Runnable 接口的任务提交给线程池,线程池会根据配置的参数调度任务执行。核心线程数内的任务会立即执行,超出核心线程数的任务会被放入任务队列中。如果任务队列已满,且线程数未达到最大线程数,线程池会创建新线程执行任务。线程池管理线程的生命周期,重用线程以减少线程创建和销毁的开销。

ExecutorService 的常用方法:

3.1 通过 void execute(Runnable command) 方法

将 Runnable 类型的任务交给线程池,线程池就会自动创建线程,自动执行 run() 方法且自动启动线程。

代码如下:

java 复制代码
import java.util.concurrent.*;
public class CreateThreadPoolExecutor {
    public static void main(String[] args) {
        Executor threadPool = new ThreadPoolExecutor(3,//核心线程数量
                5,//最大线程数量
                8,//临时线程存活时间
                TimeUnit.SECONDS,//临时线程存活时间单位
                new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4
                Executors.defaultThreadFactory(),//线程工厂,
                //用到了Executors工具类来创建默认线程工厂
                new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略:抛出异常

        //定义出Runnable类型的任务
        MyRunnable myRunnable1 = new MyRunnable();
        MyRunnable myRunnable2 = new MyRunnable();
        //将该任务提交给线程池
        threadPool.execute(myRunnable1);
        threadPool.execute(myRunnable2);
        
    }
}
class  MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "正在执行");
    }
}

运行结果:

需要注意的是,任务执行完毕之后,线程池中的线程不会销毁,还在继续运行中。

3.2 通过 void shutdown() 方法

等待全部任务执行完毕后,再关闭线程池。想要手动关闭线程池中的线程,可以用该方法,等待全部任务都执行后才会关闭。

代码如下:

java 复制代码
import java.util.concurrent.*;
public class CreateThreadPoolExecutor {
    public static void main(String[] args) {
        Executor threadPool = new ThreadPoolExecutor(3,//核心线程数量
                5,//最大线程数量
                8,//临时线程存活时间
                TimeUnit.SECONDS,//临时线程存活时间单位
                new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4
                Executors.defaultThreadFactory(),//线程工厂,
                //用到了Executors工具类来创建默认线程工厂
                new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略抛出异常

        //定义出Runnable类型的任务
        MyRunnable myRunnable1 = new MyRunnable();
        MyRunnable myRunnable2 = new MyRunnable();
        //将该任务提交给线程池
        threadPool.execute(myRunnable1);
        threadPool.execute(myRunnable2);

        //当全部任务都执行结束后,才会关闭
        ((ThreadPoolExecutor) threadPool).shutdown();

    }
}
class  MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "正在执行");
    }
}

运行结果:

3.3 通过 List<Runnable> shutdownNow() 方法

立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务。先比较与以上的方法,当前的方法就很"激进"了。不管任务结束与否,都会关闭线程池中的线程。

代码如下:

java 复制代码
import java.util.List;
import java.util.concurrent.*;
public class CreateThreadPoolExecutor {
    public static void main(String[] args) {
        Executor threadPool = new ThreadPoolExecutor(
            3,//核心线程数量
            5,//最大线程数量
            8,//临时线程存活时间
            TimeUnit.SECONDS,//临时线程存活时间单位
            new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4
            Executors.defaultThreadFactory(),//线程工厂,
            //用到了Executors工具类来创建默认线程工厂
            new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略:抛出异常

        //定义出Runnable类型的任务
        MyRunnable myRunnable1 = new MyRunnable();
        MyRunnable myRunnable2 = new MyRunnable();
        MyRunnable myRunnable3 = new MyRunnable();
        MyRunnable myRunnable4 = new MyRunnable();
        MyRunnable myRunnable5 = new MyRunnable();
        //将该任务提交给线程池
        threadPool.execute(myRunnable1);
        threadPool.execute(myRunnable2);
        threadPool.execute(myRunnable3);
        threadPool.execute(myRunnable4);
        threadPool.execute(myRunnable5);
        //还没执行完的任务会交给l链表
        List<Runnable> l = ((ThreadPoolExecutor) threadPool).shutdownNow();
        for (int i = 0; i < l.size(); i++) {
            System.out.println("还没来得及执行的任务:" + l.get(i));
        }
    }
}
class  MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "正在执行");
    }
}

运行结果:

3.4 临时线程什么时候创建?

新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。

代码如下:

java 复制代码
import java.util.concurrent.*;
public class T {
    public static void main(String[] args) {
        Executor threadPool = new ThreadPoolExecutor(3,//核心线程数量
                5,//最大线程数量
                8,//临时线程存活时间
                TimeUnit.SECONDS,//临时线程存活时间单位
                new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4
                Executors.defaultThreadFactory(),//线程工厂,
                //用到了Executors工具类来创建默认线程工厂
                new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略抛出异常

        //定义出Runnable类型的任务,此时该三个任务都被核心线程正在处理
        MyRunnable myRunnable1 = new MyRunnable();
        MyRunnable myRunnable2 = new MyRunnable();
        MyRunnable myRunnable3 = new MyRunnable();
        //这里还没到临时线程创建的时机,被放入到任务队列中等待被核心线程执行
        MyRunnable myRunnable4 = new MyRunnable();
        MyRunnable myRunnable5 = new MyRunnable();
        MyRunnable myRunnable6 = new MyRunnable();
        MyRunnable myRunnable7 = new MyRunnable();

        //此时到了临时线程创建的时机了,核心线程都在满,队列已经满了
        //创建出第一个临时线程
        MyRunnable myRunnable8 = new MyRunnable();
        //创建出第二个临时线程
        MyRunnable myRunnable9 = new MyRunnable();
        
        //将该任务提交给线程池
        threadPool.execute(myRunnable1);
        threadPool.execute(myRunnable2);
        threadPool.execute(myRunnable3);
        threadPool.execute(myRunnable4);
        threadPool.execute(myRunnable5);
        threadPool.execute(myRunnable6);
        threadPool.execute(myRunnable7);
        threadPool.execute(myRunnable8);
        threadPool.execute(myRunnable9);

    }
}

class  MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "==> 
                                                正在执行" + this);
        try {
            //在这里等待10s
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

运行结果:

当前的核心线程为 3 ,最大线程为 5 且任务队列有四个位置。当核心线程达到 3 时,且任务队列满 4 个了,还能创建临时线程时提交新任务就可以创建出临时线程了。

3.5 什么时候会开始拒绝新任务?

核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务。

代码如下:

java 复制代码
import java.util.concurrent.*;
public class T {
    public static void main(String[] args) {
        Executor threadPool = new ThreadPoolExecutor(3,//核心线程数量
                5,//最大线程数量
                8,//临时线程存活时间
                TimeUnit.SECONDS,//临时线程存活时间单位
                new ArrayBlockingQueue<>(4),//创建任务队列,最大存放任务数量为4
                Executors.defaultThreadFactory(),//线程工厂,
                //用到了Executors工具类来创建默认线程工厂
                new ThreadPoolExecutor.AbortPolicy());//拒绝策略,默认策略抛出异常

        //定义出Runnable类型的任务,此时该三个任务都被核心线程正在处理
        MyRunnable myRunnable1 = new MyRunnable();
        MyRunnable myRunnable2 = new MyRunnable();
        MyRunnable myRunnable3 = new MyRunnable();
        //这里还没到临时线程创建的时机,被放入到任务队列中等待被核心线程执行
        MyRunnable myRunnable4 = new MyRunnable();
        MyRunnable myRunnable5 = new MyRunnable();
        MyRunnable myRunnable6 = new MyRunnable();
        MyRunnable myRunnable7 = new MyRunnable();

        //此时到了临时线程创建的时机了,核心线程都在满,队列已经满了
        //创建出第一个临时线程
        MyRunnable myRunnable8 = new MyRunnable();
        //创建出第二个临时线程
        MyRunnable myRunnable9 = new MyRunnable();

        //此时核心线程都在忙,且队列已经占满了,再提交新任务的时候,
        //就会采取拒绝策略
        MyRunnable myRunnable10 = new MyRunnable();

        //将该任务提交给线程池
        threadPool.execute(myRunnable1);
        threadPool.execute(myRunnable2);
        threadPool.execute(myRunnable3);
        threadPool.execute(myRunnable4);
        threadPool.execute(myRunnable5);
        threadPool.execute(myRunnable6);
        threadPool.execute(myRunnable7);
        threadPool.execute(myRunnable8);
        threadPool.execute(myRunnable9);
        threadPool.execute(myRunnable10);

    }
}

class  MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "==> 
                                                    正在执行" + this);
        try {
            //在这里等待10s
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

运行结果:

拒绝策略默认是抛出异常

4.0 线程池处理 Callable 任务

处理Callable任务时,线程池可通过 submit() 方法提交 Callable 实例,并返回代表任务执行情况的 Future 。通过 Future 可以获取任务执行结果或处理异常。

ExecutorService 常见的方法:

4.1 通过 submit() 方法

提交 Callable 类型的任务给线程池,线程池会选择可用线程、自动执行 call() 方法、自动启动线程。

代码如下:

java 复制代码
import java.util.concurrent.*;

public class MyCreateThreadPool {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        ExecutorService executor = new ThreadPoolExecutor(
                3,
                5,
                8,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(4),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());

        //创建出Callable类型的实例对象
        MyCallable callable1 = new MyCallable(100);
        MyCallable callable2 = new MyCallable(200);
        MyCallable callable3 = new MyCallable(300);
        MyCallable callable4 = new MyCallable(400);

        //将任务提交到线程池中
        Future<String> f1 = executor.submit(callable1);
        Future<String> f2 = executor.submit(callable2);
        Future<String> f3 = executor.submit(callable3);
        Future<String> f4 = executor.submit(callable4);

        //拿到结果
        System.out.println(f1.get());
        System.out.println(f2.get());
        System.out.println(f3.get());
        System.out.println(f4.get());

    }
}

运行结果:

5.0 通过 Executors 工具类创建出线程池

Executors 工具类提供了创建不同类型线程池的方法,如 newFixedThreadPool 、 newCachedThreadPool、newSingleThreadExecutor 等。这些方法返回不同配置的线程池实例,可用于执行 Runnable 和 Callable 任务。通过 Executors 创建线程池,可方便地管理线程池的大小、任务队列、线程工厂等参数。注意合理选择线程池类型以满足任务需求,避免资源浪费或任务阻塞。

简单来说,Executors 工具类为我们提供了不同特点的线程池。

5.1 通过 Executors.newFixedThreadPool(int nThreads) 方法来创建线程池

创建固定线程数量的线程池,如果某个线程因执行异常而结束,那么线程池会补充一个新线程代替它。

代码如下:

java 复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class demo1 {
    public static void main(String[] args) {

        //固定的线程池核心线程为3,临时线程为0,所以最大线程数量也就是3。
        ExecutorService pool = Executors.newFixedThreadPool(3);

        pool.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + 
                                                        "==> 正在执行");
            }
        });
        pool.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + 
                                                        "==> 正在执行");
            }
        });
        pool.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + 
                                                        "==> 正在执行");
            }
        });
        pool.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + 
                                                        "==> 正在执行");
            }
        });
        
    }
}

运行结果:

其实 Executors.newFixedThreadPool(int nThreads) 方法的底层就是通过 ThreadPoolExecutor 类来实现创建线程池的。传入的参数就是核心线程线程数量,也为最大线程数量,因此临时线程数量为 0 。因此没有临时线程的存在,那么该线程池中的线程很固定。

如图:

5.2 通过 Executors.newCachedThreadPool() 方法来创建线程池

线程数量随着任务增加而增加,如果线程任务执行完毕且空闲了 60 s则会被回收掉。也就是有多少了任务线程池会根据任务数量动态创建新线程。

代码如下:

java 复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class demo2 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行"));

        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行"));

        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行"));

        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行"));

        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行"));

        System.out.println( ((ThreadPoolExecutor)executorService).getPoolSize());
    }
}

通过 getPoolSize() 方法可以拿到当前线程池中线程的数量。

运行结果如下:

该方法创建出来的线程池特点为,当任务越多时候,线程池中的线程数量也会随之增加。其实这个方法的底层实现也是通过 ThreadPoolExecutor 类来实现创建线程池。

如图:

很惊奇的发现,核心线程竟然是 0 个,而临时线程数量的最大值是非常非常大的,如果线程任务执行完毕且空闲了 60 s则会被回收掉。

5.3 通过 Eexcutors.newSingleThreadExecutor() 方法来创建线程池

创建只有一个线程的线程池对象,如果该线程出现异常而结束,那么线程池会补充一个新线程。

代码如下:

java 复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class demo3 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行"));
        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行"));
        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行"));
        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行"));
        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行"));
        executorService.execute(() -> System.out.println(Thread.currentThread().getName() + " ==> 正在执行"));
        
    }
}

运行结果:

因为该线程池中只有一个线程,所以该线程需要执行所有的任务。因此该方法创建出来的线程池特点是,只有一个线程。当然该方法的底层也是通过 ThreadPoolExecutor 类来试下创建线程池。

如图:

核心线程只有一个,最大线程也是一个,说明临时线程为零个。因此线程池中只有单一的线程。

6.0 新任务拒绝策略

常见的拒绝策略包括:AbortPolicy(默认策略,直接抛出异常)、CallerRunsPolicy(由调用线程执行任务)、DiscardPolicy(直接丢弃任务)、DiscardOldestPolicy(丢弃队列中最旧的任务)。

6.1 AbortPolicy(默认策略,直接抛出异常)

丢弃任务并抛出 RejectedExecutionExeception 异常,是默认的策略。

代码如下:

java 复制代码
import java.util.concurrent.*;

public class demo1 {
    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(
                2,
                3,
                8,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2),
                Executors.defaultThreadFactory(),
                //默认拒绝新任务的策略
                new ThreadPoolExecutor.AbortPolicy()
        );
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        //此时会有临时线程创建
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        //此时新任务提交的时候,会触发拒绝策略
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }
}

运行结果:

新提交的任务就被抛弃了且抛出异常。

6.2 DiscardPolicy(直接丢弃任务)

丢弃任务,但是不抛出异常,这是不推荐的做法。

代码如下:

java 复制代码
import java.util.concurrent.*;

public class demo1 {
    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(
                2,
                3,
                8,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2),
                Executors.defaultThreadFactory(),
                
                new ThreadPoolExecutor.DiscardPolicy()
        );
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        //此时会有临时线程创建
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        //此时新任务提交的时候,会触发拒绝策略
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }
}

运行结果:

6.3 CallerRunsPolicy(由调用线程执行任务)

由主线程负责调用任务的 run() 方法从而绕过线程池直接执行。

简单来说,就是交给 main 主线程执行该任务。

代码如下:

java 复制代码
import java.util.concurrent.*;

public class demo1 {
    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(
                2,
                3,
                8,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2),
                Executors.defaultThreadFactory(),
                
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        //此时会有临时线程创建
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        //此时新任务提交的时候,会触发拒绝策略
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }
}

6.4 DiscardOldestPolicy(丢弃队列中最旧的任务)

抛弃队列中等待最久的任务,然后把当前任务假如队列中。

java 复制代码
import java.util.concurrent.*;

public class demo1 {
    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(
                2,
                3,
                8,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2),
                Executors.defaultThreadFactory(),
                //默认拒绝新任务的策略
                new ThreadPoolExecutor.DiscardOldestPolicy()
        );
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        //此时会有临时线程创建
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        //此时新任务提交的时候,会触发拒绝策略
        executorService.execute(() -> {
            System.out.println(Thread.currentThread().getName() + "正在执行");
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }
}

运行结果:

相关推荐
芊寻(嵌入式)17 分钟前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习
WaaTong18 分钟前
《重学Java设计模式》之 原型模式
java·设计模式·原型模式
m0_7430484418 分钟前
初识Java EE和Spring Boot
java·java-ee
AskHarries20 分钟前
Java字节码增强库ByteBuddy
java·后端
一颗松鼠25 分钟前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
有梦想的咸鱼_27 分钟前
go实现并发安全hashtable 拉链法
开发语言·golang·哈希算法
海阔天空_201333 分钟前
Python pyautogui库:自动化操作的强大工具
运维·开发语言·python·青少年编程·自动化
天下皆白_唯我独黑40 分钟前
php 使用qrcode制作二维码图片
开发语言·php
小灰灰__40 分钟前
IDEA加载通义灵码插件及使用指南
java·ide·intellij-idea
夜雨翦春韭43 分钟前
Java中的动态代理
java·开发语言·aop·动态代理