ThreadPoolExecutor使用测试3-测试在全部任务终止后,再次向线程池提交任务

简介: ThreadPoolExecutor使用测试3-测试在全部任务终止后,再次向线程池提交任务

测试特性

  1. 测试在全部任务终止后,再次向线程池提交任务

环境

  1. jdk 1.8
  2. maven
<!-- junit test -->
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>

测试

测试用例

package concurrent;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import util.StdOut;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * ThreadPoolExecutor测试类
 */
public class ThreadPoolExecutorTest {
    /**
     * 线程池中线程索引
     */
    private final AtomicInteger pooledThreadIdx = new AtomicInteger(0);

    /**
     * 核心线程数
     */
    private final int coreSizeN = 1;

    /**
     * 最大线程数
     */
    private final int maxSizeN = 3;

    /**
     * 任务最大排队数量
     */
    private final int queueSizeM = 10;

    /**
     * 线程池中大于coreSize的线程空闲时间,单位:毫秒
     */
    private final long keepAliveTime = 60L * 1000;

    /**
     * 线程池
     */
    private ThreadPoolExecutor threadPoolExecutor;

    /**
     * 控制线程池任务执行开关
     */
    private final AtomicBoolean pass = new AtomicBoolean(false);

    @Before
    public void before() {
        // 新建线程池
        threadPoolExecutor = new ThreadPoolExecutor(
                coreSizeN,
                maxSizeN,
                keepAliveTime,
                TimeUnit.MILLISECONDS,
                // 任务队列为最大排队为10的任务队列
                new ArrayBlockingQueue<>(queueSizeM),
                // 定制ThreadFactory,定义线程名称,以在多个线程池场景下区分业务线程
                r -> new Thread(r, "executor-tester-" + pooledThreadIdx.getAndIncrement()),

                // 如果排队数量超过10,且线程最大已经达到maximumPoolSize时,再有任务提交时的拒绝策略
                // 一般是直接拒绝:表示服务仅能支撑这么多
                new ThreadPoolExecutor.AbortPolicy()
        );
    }

    /**
     * 测试在全部任务终止后,再次向线程池提交任务
     * @throws InterruptedException
     */
    @Test
    public void testAfterTerminatedReputTask() throws InterruptedException {
        // 向线程池提交n + m个任务
        submitTask(threadPoolExecutor, pass, maxSizeN + queueSizeM);
        startControlThread(pass, maxSizeN, threadPoolExecutor);
        StdOut.println("-----阶段1执行完成--------");
        StdOut.println("-----线程池任务队列大小--------:  " + threadPoolExecutor.getQueue().size());
        StdOut.println("-----重新提交新任务--------");
        // 向线程池提交m个任务
        // 如果向线程池提交超过m个任务可能会报错(注意是可能呦,因为你在提交任务的时候任务的过程中线程池中活动的线程可能已经消费了)
        // 因为此时线程池的活动线程数量为n个,在提交新任务的时候不会直接创建新的线程执行
        // 而是任务入队,如果超过任务队列大小m,则会执行执行拒绝策略抛出异常
        pass.set(false);
        submitTask(threadPoolExecutor, pass, queueSizeM);
        startControlThread(pass, maxSizeN, threadPoolExecutor);
    }

    /**
     * 提交任务到线程池
     * @param threadPoolExecutor 线程池
     * @param pass 任务控制开关
     * @param taskCount 任务数量
     */
    private void submitTask(ThreadPoolExecutor threadPoolExecutor, AtomicBoolean pass, int taskCount) {
        for (int i = 0; i < taskCount; i++) {
            threadPoolExecutor.execute(() -> {
                while (!pass.get()) {
                    StdOut.println(Thread.currentThread().getName() + ": Thread running..." );
                    sleep(1000);
                }
            });
        }
    }

    /**
     * 睡眠
     * @param millis 睡眠时间,单位:毫秒
     */
    public static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 控制线程池中任务执行的线程
     * @param pass 任务执行开关 true:任务执行,false:任务睡眠
     * @param maxSizeN  线程池中最大线程数量
     * @param threadPoolExecutor 线程池
     * @throws InterruptedException
     */
    private void startControlThread(AtomicBoolean pass, int maxSizeN, ThreadPoolExecutor threadPoolExecutor) throws InterruptedException {
        // 控制线程
        Thread controlThread = new Thread(() -> {
            int i = 0;
            while (i++ < 10) {
                // 先将自己睡眠一秒防止线程池还没有“反应过来”就获取活动线程数量为0的问题
                sleep(1000);

                // 睡眠一秒后再获取活动的线程数量应该为1,
                Assert.assertEquals(maxSizeN, threadPoolExecutor.getActiveCount());
                StdOut.println("thread pool running workers: " + threadPoolExecutor.getActiveCount());
            }

            // 将线程中的任务全部放行
            pass.set(true);

            i = 0;
            // 等待大约2秒时间再判断线程池中的活动线程数量应该为0
            // 因为任务已经执行完成了
            while (i++ < 10) {
                sleep(200);
                StdOut.println("thread pool running workers: " + threadPoolExecutor.getActiveCount());
            }
            Assert.assertEquals(0, threadPoolExecutor.getActiveCount());
            StdOut.println("thread pool running workers: " + threadPoolExecutor.getActiveCount());
        });
        controlThread.start();
        controlThread.join();
    }

}

Console输出

executor-tester-2: Thread running...
executor-tester-0: Thread running...
executor-tester-1: Thread running...
executor-tester-2: Thread running...
executor-tester-0: Thread running...
executor-tester-1: Thread running...
thread pool running workers: 3
executor-tester-0: Thread running...
executor-tester-1: Thread running...
thread pool running workers: 3
executor-tester-2: Thread running...
executor-tester-1: Thread running...
executor-tester-2: Thread running...
executor-tester-0: Thread running...
thread pool running workers: 3
executor-tester-1: Thread running...
thread pool running workers: 3
executor-tester-0: Thread running...
executor-tester-2: Thread running...
executor-tester-0: Thread running...
executor-tester-1: Thread running...
executor-tester-2: Thread running...
thread pool running workers: 3
executor-tester-2: Thread running...
thread pool running workers: 3
executor-tester-1: Thread running...
executor-tester-0: Thread running...
executor-tester-0: Thread running...
executor-tester-2: Thread running...
executor-tester-1: Thread running...
thread pool running workers: 3
executor-tester-2: Thread running...
thread pool running workers: 3
executor-tester-0: Thread running...
executor-tester-1: Thread running...
executor-tester-0: Thread running...
thread pool running workers: 3
executor-tester-1: Thread running...
executor-tester-2: Thread running...
executor-tester-2: Thread running...
executor-tester-0: Thread running...
executor-tester-1: Thread running...
thread pool running workers: 3
thread pool running workers: 3
thread pool running workers: 3
thread pool running workers: 3
thread pool running workers: 3
thread pool running workers: 3
thread pool running workers: 0
thread pool running workers: 0
thread pool running workers: 0
thread pool running workers: 0
thread pool running workers: 0
thread pool running workers: 0
-----阶段1执行完成--------
-----线程池任务队列大小--------:  0
-----重新提交新任务--------
executor-tester-0: Thread running...
executor-tester-1: Thread running...
executor-tester-2: Thread running...
executor-tester-0: Thread running...
thread pool running workers: 3
executor-tester-1: Thread running...
executor-tester-2: Thread running...
thread pool running workers: 3
executor-tester-1: Thread running...
executor-tester-0: Thread running...
executor-tester-2: Thread running...
executor-tester-2: Thread running...
thread pool running workers: 3
executor-tester-0: Thread running...
executor-tester-1: Thread running...
executor-tester-2: Thread running...
executor-tester-0: Thread running...
executor-tester-1: Thread running...
thread pool running workers: 3
executor-tester-0: Thread running...
executor-tester-1: Thread running...
executor-tester-2: Thread running...
thread pool running workers: 3
executor-tester-2: Thread running...
thread pool running workers: 3
executor-tester-0: Thread running...
executor-tester-1: Thread running...
executor-tester-1: Thread running...
executor-tester-0: Thread running...
thread pool running workers: 3
executor-tester-2: Thread running...
executor-tester-2: Thread running...
thread pool running workers: 3
executor-tester-1: Thread running...
executor-tester-0: Thread running...
executor-tester-0: Thread running...
executor-tester-1: Thread running...
executor-tester-2: Thread running...
thread pool running workers: 3
executor-tester-0: Thread running...
executor-tester-1: Thread running...
thread pool running workers: 3
executor-tester-2: Thread running...
thread pool running workers: 3
thread pool running workers: 3
thread pool running workers: 3
thread pool running workers: 3
thread pool running workers: 1
thread pool running workers: 0
thread pool running workers: 0
thread pool running workers: 0
thread pool running workers: 0
thread pool running workers: 0
thread pool running workers: 0
目录
相关文章
|
2月前
|
存储 Java 数据库
如何处理线程池关闭时未完成的任务?
总之,处理线程池关闭时未完成的任务需要综合考虑多种因素,并根据实际情况选择合适的处理方式。通过合理的处理,可以最大程度地减少任务丢失和数据不一致等问题,确保系统的稳定运行和业务的顺利开展。
126 64
|
2月前
|
消息中间件 监控 Java
线程池关闭时未完成的任务如何保证数据的一致性?
保证线程池关闭时未完成任务的数据一致性需要综合运用多种方法和机制。通过备份与恢复、事务管理、任务状态记录与恢复、数据同步与协调、错误处理与补偿、监控与预警等手段的结合,以及结合具体业务场景进行分析和制定策略,能够最大程度地确保数据的一致性,保障系统的稳定运行和业务的顺利开展。同时,不断地优化和改进这些方法和机制,也是提高系统性能和可靠性的重要途径。
124 62
|
2月前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
57 12
|
3月前
|
机器学习/深度学习 编解码 监控
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章详细介绍了如何使用YOLOv8进行目标检测任务,包括环境搭建、数据准备、模型训练、验证测试以及模型转换等完整流程。
3783 1
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
3月前
|
机器学习/深度学习 监控 计算机视觉
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
本文介绍了如何使用YOLOv7进行目标检测,包括环境搭建、数据集准备、模型训练、验证、测试以及常见错误的解决方法。YOLOv7以其高效性能和准确率在目标检测领域受到关注,适用于自动驾驶、安防监控等场景。文中提供了源码和论文链接,以及详细的步骤说明,适合深度学习实践者参考。
661 0
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
3月前
|
机器学习/深度学习 并行计算 数据可视化
目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用PaddleClas框架完成多标签分类任务,包括数据准备、环境搭建、模型训练、预测、评估等完整流程。
185 0
|
3月前
|
机器学习/深度学习 数据采集 算法
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
这篇博客文章介绍了如何使用包含多个网络和多种训练策略的框架来完成多目标分类任务,涵盖了从数据准备到训练、测试和部署的完整流程,并提供了相关代码和配置文件。
71 0
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
|
3月前
|
机器学习/深度学习 XML 并行计算
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用YOLOX完成图像目标检测任务的完整流程,包括数据准备、模型训练、验证和测试。
267 0
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
3月前
|
缓存 负载均衡 Java
c++写高性能的任务流线程池(万字详解!)
本文介绍了一种高性能的任务流线程池设计,涵盖多种优化机制。首先介绍了Work Steal机制,通过任务偷窃提高资源利用率。接着讨论了优先级任务,使不同优先级的任务得到合理调度。然后提出了缓存机制,通过环形缓存队列提升程序负载能力。Local Thread机制则通过预先创建线程减少创建和销毁线程的开销。Lock Free机制进一步减少了锁的竞争。容量动态调整机制根据任务负载动态调整线程数量。批量处理机制提高了任务处理效率。此外,还介绍了负载均衡、避免等待、预测优化、减少复制等策略。最后,任务组的设计便于管理和复用多任务。整体设计旨在提升线程池的性能和稳定性。
89 5
|
5月前
|
前端开发 JavaScript 大数据
React与Web Workers:开启前端多线程时代的钥匙——深入探索计算密集型任务的优化策略与最佳实践
【8月更文挑战第31天】随着Web应用复杂性的提升,单线程JavaScript已难以胜任高计算量任务。Web Workers通过多线程编程解决了这一问题,使耗时任务独立运行而不阻塞主线程。结合React的组件化与虚拟DOM优势,可将大数据处理等任务交由Web Workers完成,确保UI流畅。最佳实践包括定义清晰接口、加强错误处理及合理评估任务特性。这一结合不仅提升了用户体验,更为前端开发带来多线程时代的全新可能。
119 1