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
目录
相关文章
|
29天前
|
存储 监控 Java
|
1月前
|
资源调度 Java 调度
项目环境测试问题之Schedulerx2.0通过分布式分片任务解决单机计算瓶颈如何解决
项目环境测试问题之Schedulerx2.0通过分布式分片任务解决单机计算瓶颈如何解决
项目环境测试问题之Schedulerx2.0通过分布式分片任务解决单机计算瓶颈如何解决
|
1月前
|
监控 Java
ThreadPoolExecutor 线程执行超时,释放线程
ThreadPoolExecutor 线程执行超时,释放线程
33 1
|
20天前
|
前端开发 JavaScript 大数据
React与Web Workers:开启前端多线程时代的钥匙——深入探索计算密集型任务的优化策略与最佳实践
【8月更文挑战第31天】随着Web应用复杂性的提升,单线程JavaScript已难以胜任高计算量任务。Web Workers通过多线程编程解决了这一问题,使耗时任务独立运行而不阻塞主线程。结合React的组件化与虚拟DOM优势,可将大数据处理等任务交由Web Workers完成,确保UI流畅。最佳实践包括定义清晰接口、加强错误处理及合理评估任务特性。这一结合不仅提升了用户体验,更为前端开发带来多线程时代的全新可能。
22 0
|
1月前
|
Cloud Native Java 调度
项目环境测试问题之线程同步器会造成执行完任务的worker等待的情况如何解决
项目环境测试问题之线程同步器会造成执行完任务的worker等待的情况如何解决
|
1月前
|
Java 测试技术
Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
23 0
|
1月前
|
Java 测试技术 PHP
父子任务使用不当线程池死锁怎么解决?
在Java多线程编程中,线程池有助于提升性能与资源利用效率,但若父子任务共用同一池,则可能诱发死锁。本文通过一个具体案例剖析此问题:在一个固定大小为2的线程池中,父任务直接调用`outerTask`,而`outerTask`再次使用同一线程池异步调用`innerTask`。理论上,任务应迅速完成,但实际上却超时未完成。经由`jstack`输出的线程调用栈分析发现,线程陷入等待状态,形成“死锁”。原因是子任务需待父任务完成,而父任务则需等待子任务执行完毕以释放线程,从而相互阻塞。此问题在测试环境中不易显现,常在生产环境下高并发时爆发,重启或扩容仅能暂时缓解。
|
2月前
|
Java Linux
Java演进问题之1:1线程模型对于I/O密集型任务如何解决
Java演进问题之1:1线程模型对于I/O密集型任务如何解决
|
2月前
|
SQL DataWorks Java
DataWorks操作报错合集之在本地任务和冒烟测试中可以正常运行,但在调度任务中报错,是什么原因
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
|
2月前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
60 1