小工具      在线工具  汉语词典  css  js  c++  java

ThreadPoolExecutor 线程池解析

Java 额外说明

收录于:42天前

一。ThreadPoolExecuror类的构造方法中各个参数的含义:
public ThreadPoolExecutor (int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue)

corePoolSize:线程池中保存的核心线程数,包括空闲线程。

MaximumPoolSize:池中允许的最大线程数。

keepAliveTime:线程池中空闲线程可以持续的最长时间。

单位:持续时间的单位。

workQueue:执行前保存任务的队列。只保存execute方法提交的Runnable任务。


根据ThreadPoolExecutor源码前面大段的注释,我们可以看出,当试图通过excute方法将一个Runnable任务添加到线程池中时,按照如下顺序来处理:
    1、如果线程池中的线程数量少于corePoolSize,即使线程池中有空闲线程,也会创建一个新的线程来执行新添加的任务;
    2、如果线程池中的线程数量大于等于corePoolSize,但缓冲队列workQueue未满,则将新添加的任务放到workQueue中,按照FIFO的原则依次等待执行(线程池中有线程空闲出来后依次将缓冲队列中的任务交付给空闲的线程执行);

3、如果线程池中的线程数大于等于corePoolSize,且缓冲队列workQueue已满,但线程池中的线程数小于maximumPoolSize,则会创建一个新的线程来处理添加任务;


  4、如果线程池中的线程数量等于了maximumPoolSize,有4种处理方式(该构造方法调用了含有5个参数的构造方法,并将最后一个构造方法为RejectedExecutionHandler类型,它在处理线程溢出时有4种方式,这里不再细说,要了解的,自己可以阅读下源码)。

总结一下,也就是说,当有新的任务需要处理时,首先检查线程池中的线程数是否大于corePoolSize,然后检查缓冲队列workQueue是否已满,最后检查是否线程池中的线程数大于maximumPoolSize。

另外,当线程池中的线程数大于corePoolSize时,如果有线程的空闲时间超过keepAliveTime,则会将其从线程池中移除。这样就可以动态调整线程池中的线程数量。

二。多线程测试demo

下面的例子,核心线程数为3,总线程数为5,总任务数为10,任务队列长度为5(new LinkedBlockingQueue<Runnable>(5))此时执行的是上面方式3的这种情况(红色字体)

通过下面的打印日志,可以看出workQueue已满,线程总数小于5,所以这里又创建了2个非核心的线程,用来执行任务:

16:02:00,271  INFO TestThread:101 - 当前的线程是:pool-1-thread-4
16:02:00,271  INFO TestThread:101 - 当前的线程是:pool-1-thread-5

private final ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3 ,5 ,100 ,
            TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(5));

    @Test
    public void testThreadPoolExecutor() throws ExecutionException, InterruptedException {

        logger.info("start testThreadPoolExecutor....");

        List<Future<String>> futureList = new ArrayList<>();
        for (Integer i = 0; i < 10; i++) {
            Future<String> future = poolExecutor.submit(new Callable<String>() {
                @Override
                public String call() throws Exception{

                    Thread.sleep(1000);
                    return "当前的线程是:" + Thread.currentThread().getName();
                }
            });
            futureList.add(future);
        }

        logger.info("perform  testThreadPoolExecutor....");

        for (Future future : futureList) {

            try {
                logger.info(future.get().toString());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        logger.info("end  testThreadPoolExecutor....");

    }

三。日志分析:

start testThreadPoolExecutor....
perform  testThreadPoolExecutor....

因为上面两条日志是顺序执行的,所以这里可以看到ThreadPoolExecutor直接提交了多个任务(此时任务还没有开始执行),而且它只是提交了任务。

然后使用Future接收每个线程的返回值。此时没有真正的返回值。这里只是给Future对象赋值的一个标记(这里使用了函数指针的概念,当这里返回一个值时,立即将值传递给Future对象)。关于未来,大家可以看看我上面几篇文章。

任务的实际执行在这段代码中:logger.info(future.get().toString());

这里的future.get()会阻塞等待之前提交的任务的执行结果。如果没有返回结果,则会等到有结果返回后才执行下面的代码。

. . .

相关推荐

额外说明

Spring IOC原理源码分析(@Autowired原理详解:识别属性和方法)(二)

源码推荐看这篇博客的时候打开Spring源码,一边看源码,一边看博客上代码的关键处的注释,这样能更好的理解Spring IOC的流程及内部实现和使用方法。如果你对IOC的原理有些了解,则这些注释能帮你更深入的理解其实现方式。 Spring容器在每个Bea

额外说明

PostgreSQL 安装脚本 pgsql_admin_script install_pgxl.txt

PostgreSQL 安装脚本 pgsql_admin_script install_pgxl.txt vi env_xl.sh export PS1="$USER@`/bin/hostname -s`-> " export PGPORT=1991

额外说明

buuctf: 莫斯

下载解压直接接得到题目.txt打开发现摩斯密码, 直接摩斯密码解密得到flag (要包上flag{})。

额外说明

蚂蚁CTO线已经经过五年的测试和开发,并将在年后进行优化。让我告诉你几句话。

夙兴夜寐,回顾从毕业出来到现在的这五年,也是在这里给大家抛砖引玉了。 先简单交代一下背景吧,某不知名 985 的本硕,17 年毕业加入蚂蚁金服,以“人员优化”的名义无情被裁员,之后跳槽到了有赞,一直从事软件测试的工作。之前没有实习经历,算是5年的工作经验

额外说明

【java】输入Hello java

Code: package test; public class hello { public static void main(String[] args) { System.out.println("Hello java"); } }

额外说明

linux安装jdk(RPM方式和tar.gz方式)

       安装有两个过程,第一个是下载,第二个是安装。安装之前要下载Java的安装包,在下载之前,我们先来掰扯一下Java的各种版本。众所周知,Java是免费开源的,这里的开源有两层含义,第一是Java本身是开源的,第二其规范也是开源的。这也就意味着

额外说明

ch2_2系统调用的实现

0. 整体调用过程 在通常情况下,调用系统调用和调用一个普通的自定义函数在代码上并没有什么区别, 但调用后发生的事情有很大不同。 调用自定义函数是通过 call 指令直接跳转到该函数的地址,继续运行。 而系统调用调用的过程如下: 应用程序 调用接口函数

额外说明

maven常用命令总结

工作后才会发现各种指令操作都是常有的事,要是等用的时候一个个去查那就太慢了,还是要去记一些常用的命令的。 Maven常用命令: 编译源代码: mvn compile 2. 编译测试代码:mvn test-compile 3. 运行测试:mvn test

额外说明

【Java面试小短文】Spring 如何解决循环依赖?

欢迎关注Java面试系列,不定期更新面试小短文。欢迎一键三连! 文章目录 一、Spring 发生循环依赖的原因 二、循环依赖的三种形态 三、循环依赖问题如何解决? 四、三级缓存的作用是什么? 五、Spring 中哪些情况下,不能解决循环依赖问题? 一、S

额外说明

Javascript 经纬度正则表达式

// 经度正则表达式,范围:-180.0000~180.0000 let lngReg = '^-?((1?[0-7]?[0-9]?)(([.][0-9]{1,4})?)|180(([.][0]{1,4})?))$'; // 纬度正则表达式,范围:-9

ads via 小工具