Operations 12 min read

Building a Java Multithreaded Performance Testing Framework: Base and Execution Classes

This article explains how to design a Java performance testing framework by defining an abstract multithreaded base class for common behaviors, implementing two virtual classes for different load‑testing modes, and creating an execution class that orchestrates thread pools, collects metrics, and generates visual reports, with full source code examples and a Gitee repository link.

FunTester
FunTester
FunTester
Building a Java Multithreaded Performance Testing Framework: Base and Execution Classes

Overview

The article describes a Java performance‑testing framework built around a reusable abstract base class ( ThreadBase) that standardises common test behaviours, two virtual mode classes for quantitative and timed load testing, and an execution class ( Concurrent) that manages thread pools, aggregates results and produces textual visualisation.

ThreadBase – Multithreaded Task Base Class

ThreadBase

is an abstract generic class ( <T extends Serializable>) that implements Runnable. It defines the following core fields: errorNum – number of errors recorded during execution. excuteNum – total number of executions (normally matches the count of response‑time records). countDownLatch – a CountDownLatch set by the execution class for synchronisation. mark – a MarkThread object used for request tagging. t – the generic resource passed to the task (useful when the outer instance is inaccessible).

Concrete test tasks must implement three abstract methods: before() – preparation before the test logic runs. doing() – the actual test logic; may throw Exception to count an error. after() – post‑processing; the default implementation counts down the latch.

Additional utility methods include: getTString() – returns t.toString() for Groovy compatibility. clone() – deep‑copies the task instance. status() – indicates whether the task should terminate early (default false). multiply(int num) – creates a list of num cloned task instances.

Concurrent – Execution Class

Concurrent

drives the load test. Key configuration fields are: threadNum – number of concurrent threads. threads – list of ThreadBase instances (cloned as needed). desc – description string, default "FunTester". allTimes – static Vector<Long> that records every response time. requestMark – static Vector<String> that records request tags. executorService – fixed‑size thread pool. countDownLatch – synchronisation aid matching the thread count.

Constructors allow creation from a single task template, a list of tasks, or a task list with a custom description. All constructors initialise the thread pool and latch.

The start() method performs the following steps:

Record the start timestamp.

Iterate over the thread list, assign the latch to each task and submit it to the executor.

Wait for all threads to finish via shutdownService(), then record the end timestamp.

Aggregate error, failure and execution counts from each task.

Log a summary line with total threads, duration, execution count, error count and failure count.

Call over() to persist raw timing data, clear static vectors and compute final performance metrics. shutdownService() safely shuts down the executor after the latch reaches zero. over() saves the collected times and request marks, resets the static containers and invokes countQPS() to calculate QPS and other statistics.

The countQPS(...) family reads the persisted timing file, converts each line to an integer, computes the sum, sorts the data and calculates queries‑per‑second as 1000.0 * size * threadNum / sum. It returns a PerformanceResultBean containing the description, start/end timestamps, thread count, request count, average latency, QPS, error/failure percentages and a textual histogram generated by statistics(...).

Result Visualization

The statistics(List<Integer> data, String title) method builds a bucketed histogram of response‑time distribution. It partitions the sorted data into a configurable number of buckets, selects the median of each bucket, and renders a two‑dimensional string array as a text‑based chart that includes min/max values and bucket indices.

Repository

Source code is hosted at https://gitee.com/fanapi/tester. Users can clone the repository, extend ThreadBase with custom test logic, and instantiate Concurrent to run load tests with configurable thread counts and descriptions.

Important Notes

The attribute failNum mentioned in the original article is not a field of ThreadBase; it belongs to the execution class Concurrent as the status field.

The framework records both raw timing data and request markers for later analysis.

All visual output is text‑based; external charting tools can be used by processing the generated files.

Performance testing framework visualization
Performance testing framework visualization
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaconcurrencyPerformance TestingmultithreadingCode ExampleFramework
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.