Implementing Multi‑Threaded HTTP Load Tests in Java

This article explains how to build two Java load‑testing modes—quantitative and timed—by extending thread‑limit classes, managing GCThread lifecycle, sending HTTP requests with FanLibrary, and correctly cloning request objects to avoid bugs during multithreaded performance testing.

FunTester
FunTester
FunTester
Implementing Multi‑Threaded HTTP Load Tests in Java
Believe in the theory of ten thousand lines of code!

Continuing from the previous post that introduced abstract classes for timed and quantitative load‑testing modes, this article presents concrete implementations for a single HTTP request object ( HTTPrequestbase) in a multithreaded performance testing framework.

The key points are starting and stopping GCThread in the before() method and implementing the doing() method to send the request and parse the response. Response validation and assertions are omitted because they are highly context‑specific and often unnecessary; monitoring server logs or other metrics can be used instead.

It is crucial to correctly clone objects—both multithreaded class instances and HTTPrequestbase objects—by implementing a clone() method; otherwise, bugs may arise.

Gitee repository: https://gitee.com/fanapi/tester

Quantitative Mode

package com.fun.frame.thead;

import com.fun.base.constaint.ThreadLimitTimesCount;
import com.fun.base.interfaces.MarkThread;
import com.fun.frame.httpclient.FanLibrary;
import com.fun.frame.httpclient.FunRequest;
import com.fun.frame.httpclient.GCThread;
import org.apache.http.client.methods.HttpRequestBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * http request multithread class
 */
public class RequestThreadTimes extends ThreadLimitTimesCount {
    static Logger logger = LoggerFactory.getLogger(RequestThreadTimes.class);
    public HttpRequestBase request;

    /**
     * Constructor for multiple executions per thread
     * @param request the request to execute
     * @param times   number of executions per thread
     */
    public RequestThreadTimes(HttpRequestBase request, int times) {
        super(null, times, null);
        this.request = request;
    }

    /**
     * Constructor with marking support
     */
    public RequestThreadTimes(HttpRequestBase request, int times, MarkThread mark) {
        super(null, times, mark);
        this.request = request;
    }

    protected RequestThreadTimes() { super(); }

    @Override
    public void before() {
        super.before();
        GCThread.starts();
    }

    @Override
    protected void doing() throws Exception {
        FanLibrary.excuteSimlple(request);
    }

    @Override
    public RequestThreadTimes clone() {
        RequestThreadTimes threadTimes = new RequestThreadTimes();
        threadTimes.times = this.times;
        threadTimes.request = FunRequest.cloneRequest(request);
        threadTimes.mark = mark == null ? null : mark.clone();
        return threadTimes;
    }
}

Timed Mode

package com.fun.frame.thead;

import com.fun.base.constaint.ThreadLimitTimeCount;
import com.fun.base.interfaces.MarkThread;
import com.fun.frame.httpclient.FanLibrary;
import com.fun.frame.httpclient.FunRequest;
import com.fun.frame.httpclient.GCThread;
import org.apache.http.client.methods.HttpRequestBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * http request multithread class
 */
public class RequestThreadTime extends ThreadLimitTimeCount {
    static Logger logger = LoggerFactory.getLogger(RequestThreadTime.class);
    public HttpRequestBase request;

    /**
     * Constructor for multiple executions per thread
     * @param request the request to execute
     * @param time    number of executions per thread
     */
    public RequestThreadTime(HttpRequestBase request, int time) {
        super(null, time, null);
        this.request = request;
    }

    /**
     * Constructor with marking support
     */
    public RequestThreadTime(HttpRequestBase request, int time, MarkThread mark) {
        super(null, time, mark);
        this.request = request;
    }

    protected RequestThreadTime() { super(); }

    @Override
    public void before() {
        super.before();
        GCThread.starts();
    }

    @Override
    protected void doing() throws Exception {
        FanLibrary.excuteSimlple(request);
    }

    @Override
    public RequestThreadTime clone() {
        RequestThreadTime threadTime = new RequestThreadTime();
        threadTime.time = this.time;
        threadTime.request = FunRequest.cloneRequest(request);
        threadTime.mark = mark == null ? null : mark.clone();
        return threadTime;
    }
}

Disclaimer: "FunTester" is released for the first time; please follow and discuss, and third‑party reposting is prohibited.

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.

BackendJavaPerformance TestingLoad TestingHTTPmultithreading
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.