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

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

文章目录

        1.0 线程池概述

        1.1 线程池的优点

        1.2 不使用线程池的问题

        1.3 线程池的工作原理图

        1.4 如何创建线程池? 

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

        2.1 ThreadPoolExecutor 构造器

        3.0 线程池处理 Runnable 任务

        3.1 通过 void execute(Runnable command) 方法

        3.2 通过 void shutdown() 方法

        3.3 通过 List shutdownNow() 方法

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

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

        4.0 线程池处理 Callable 任务

        4.1 通过 submit() 方法

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

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

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

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

        6.0 新任务拒绝策略

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

        6.2 DiscardPolicy(直接丢弃任务)

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

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


        1.0 线程池概述

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

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

        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:指定线程池的任务拒绝策略(线程都在忙,任务队列也满的时候,新任务来了该怎么处理)。

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

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() 方法且自动启动线程。

代码如下:

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() 方法

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

代码如下:

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() 方法

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

代码如下:

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 临时线程什么时候创建?

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

代码如下:

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 什么时候会开始拒绝新任务?

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

代码如下:

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() 方法、自动启动线程。

代码如下:

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) 方法来创建线程池

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

代码如下:

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则会被回收掉。也就是有多少了任务线程池会根据任务数量动态创建新线程。

代码如下:

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() 方法来创建线程池

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

代码如下:

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 异常,是默认的策略。

代码如下:

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(直接丢弃任务)

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

代码如下:

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 主线程执行该任务。

代码如下:

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(丢弃队列中最旧的任务)

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

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);
            }
        });
    }
}

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/522869.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关于交叉小波变换

小波变换可以很好的在时频域中分析单个信号的瞬态和突变等时变特性&#xff0c;交叉小波变换是在小波变换的基础上提出的&#xff0c; 主要用来处理两个信号之间的相关程度。传统的互相关分析方法&#xff0c; 是通过傅里叶变换将信号从时域上转换到频域上&#xff0c;然后在频…

neo4j图数据库下载安装配置

neo4j下载地址Index of /doc/neo4j/3.5.8/ 1.说明&#xff1a;jdk 1.8 版本对应的 neo4j 数据库版本 推荐安装3.X版本 2.配置系统环境变量 3.启动 neo4j.bat console 4.访问

ENSP防火墙,解决不兼容及报错等问题,windows命令行修改网卡配置,配置cloud及防火墙连接,web连接防火墙

解决不兼容和报错等问题 原因1&#xff1a;VirtualBox版本太低&#xff08;5.1.x&#xff09;或太高&#xff08;6.x.x&#xff09;和eNSP不兼容 卸载virtualbox&#xff0c;下载virtualbox 5.2.28&#xff0c;安装稳定版本的virtualbox 删除原有程序&#xff1a;c:\用户\***\.…

烤羊肉串引来的思考--命令模式

1.1 吃羊肉串&#xff01; 烧烤摊旁边等着拿肉串的人七嘴八舌地叫开了。场面有些混乱&#xff0c;由于人实在太多&#xff0c;烤羊肉串的老板已经分不清谁是谁&#xff0c;造成分发错误&#xff0c;收钱错误&#xff0c;烤肉质量不过关等。 外面打游击烤羊肉串和这种开门店做烤…

FSQ8罗德与施瓦茨FSQ8信号分析仪

181/2461/8938产品概述&#xff1a; R&S FSQ8 信号分析仪将两种仪器合二为一。它提供高达 120 MHz 解调带宽的信号分析以及高端频谱分析仪的动态范围。 频率范围&#xff1a;20 Hz 至 8 GHz高端频谱分析仪的动态范围 TOI 25 dBm&#xff0c;典型值1 dB 压缩 13 dBm&…

【已解决】HalconDotNet.HOperatorException:“HALCON error #1201: Wrong type of control

前言 最近在学习Halcon视觉和C#的联合开发&#xff0c;碰到一个比较有意思的问题记录一下&#xff0c;大致的报错信息是说我用的halcondotnet版本和我在halcon导出的使用的halcondotnet.dll版本不一致&#xff0c;所以才报错的&#xff01; 解决 首先你得找到你安装halcon的…

安全测试概述和用例设计

一、安全测试概述 定义&#xff1a;安全测试是在软件产品开发基本完成时&#xff0c;验证产品是否符合安全需求定义和产品质量标准的过程。 概念&#xff1a;安全测试是检查系统对非法侵入渗透的防范能力。 准则&#xff1a;理论上来讲&#xff0c;只要有足够的时间和资源&a…

哈希字典Dict

目录 Dict的组成 1.hash表的节点 2.hash表结构 3.字典 4.Dict结构 hash算法 哈希函数 什么情况下使用 rehash rehash主要的函数dictExpand 怎么判断要进行扩容还是收缩 什么时候会用到扩展和收缩 渐进式rehash 渐进式rehash主要的函数dictRehash 字典API 字典的…

shopee虾皮运营技巧,学会这几招能有效提高销量

在电商的运营过程中&#xff0c;新手总会踩上不少的坑&#xff0c;运气好的累计成经验值&#xff0c;应用于日后的店铺运营中&#xff0c;运气不好的&#xff0c;进坑了就再也爬不上来了&#xff0c;特别是跨境电商&#xff0c;本身与国内电商存在很大的信息差&#xff0c;不可…

【EI会议】2024年机械制造、航天工程技术与材料应用国际学术会议 (MMAETMA 2024)

2024 International Academic Conference on Mechanical Manufacturing, Aerospace Engineering Technology and Materials Application (MMAETMA 2024) 会议地点&#xff1a;长沙&#xff0c;中国 截稿时间&#xff1a;2024.4.30 网址&#xff1a;http://www.mmaetma.com/ …

Linux环境下安装redis踩坑zmalloc.h:50:31收录(附解决方法)

老将回归第一篇问题收录&#xff08;苦笑&#xff09; 报错收录 解决&#xff1a;zmalloc.h:50:31: 致命错误&#xff1a;jemalloc/jemalloc.h&#xff1a;没有文件或目录 解法一&#xff1a; # 执行如下命令 MALLOC环境变量去建立Redis的libcmake MALLOClibc解决 解法二&a…

FJSP:霸王龙优化算法(Tyrannosaurus optimization,TROA)求解柔性作业车间调度问题(FJSP),提供MATLAB代码

一、柔性作业车间调度问题 柔性作业车间调度问题&#xff08;Flexible Job Shop Scheduling Problem&#xff0c;FJSP&#xff09;&#xff0c;是一种经典的组合优化问题。在FJSP问题中&#xff0c;有多个作业需要在多个机器上进行加工&#xff0c;每个作业由一系列工序组成&a…

企业IT运维事中故障定位方法及工具

企业IT故障定位指诊断故障直接原因或根因&#xff0c;故障定位有助于故障恢复动作更加有效。故障定位通常是整个故障过程中耗时最长的环节&#xff0c;定位的目标围绕在快速恢复的基础上&#xff0c;而非寻找问题根因&#xff0c;后者由问题管理负责。通常大部分可用性故障&…

电脑桌面监控软件

电脑桌面监控软件 有一项触目精心的统计&#xff0c;2022年上半年&#xff0c;有33.2%的网民在单位上网&#xff0c;上网行为包括聊天、游戏、看小说、炒股等等&#xff0c;可以说五花八门。这些行为给企业带来四个问题&#xff1a; &#xff08;1&#xff09;宽带资源被滥用。…

Myelsa的Python函数之旅(高铁直达)

一、函数的定义&#xff1a; 函数(Function)是一段可重复使用的代码块&#xff0c;用于执行特定的任务或计算&#xff0c;并可以接受输入参数和返回输出结果。函数可以将复杂的问题分解为更小的子问题&#xff0c;提高代码的可读性和可维护性。 二、函数的组成&#xff1a; 在…

面试:HashMap

目录 1、底层数据结构&#xff0c;1.7 与1.8有何不同? 2、为何要用红黑树&#xff0c;为何一上来不树化&#xff0c;树化阈值为何是8&#xff0c;何时会树化&#xff0c;何时会退化为链表? 3、索引如何计算? hashCode都有了&#xff0c;为何还要提供hash()方法?数组容量为…

java实现运行脚本文件

在最近的项目中&#xff0c;有一个需求是前端传给我一个脚本文件&#xff0c;然后我需要运行脚本文件后将结果进行返回&#xff0c;那接下来就让我们看看是怎么做的吧&#xff01; public R runScripts(Integer id) {ScriptsInfo scriptsInfo this.baseMapper.selectById(id);…

【数据结构】红黑树详解

目录 前言&#xff1a; 红黑树的概念&#xff1a; 红黑树的性质: 红黑树节点的定义&#xff1a; 红黑树的插入&#xff1a; 情况1&#xff1a;cur为红&#xff0c;p为红&#xff0c;g为黑&#xff0c;u存在且为红 情况2&#xff1a;cur为红&#xff0c;p为红&#xff0c…

CY5.5-NH2生物分子荧光标记Cy5.5 星戈瑞

CY5.5-NH2是一种常用的生物分子荧光标记染料&#xff0c;属于Cy5.5系列染料的一种。它具有强烈的荧光信号和较高的光稳定性&#xff0c;因此在生物分子标记和成像领域得到应用。 CY5.5-NH2染料具有一个氨基(-NH2)官能团&#xff0c;可以与生物分子中的羧基(-COOH)或其他活性基…

linux网络预备

网络预备 网络协议初识 协议分层 打电话例子 在这个例子中, 我们的协议只有两层; 但是实际的网络通信会更加复杂, 需要分更多的层次。 分层最大的好处在于 “封装” 。 OSI七层模型 OSI&#xff08;Open System Interconnection&#xff0c;开放系统互连&#xff09;七层网…