Simulating Delayed Order Cancellation with Java DelayQueue for Performance Testing

This article explains how to meet a performance‑testing requirement for cancelling orders 10 seconds after placement by leveraging Java's thread‑safe DelayQueue, detailing the design, implementation, test case, execution steps, and observed results.

FunTester
FunTester
FunTester
Simulating Delayed Order Cancellation with Java DelayQueue for Performance Testing

The author initially believed their performance‑testing scenarios were complete, but a new requirement to cancel orders 10 seconds after placement revealed a gap.

Requirement

In a specific test, orders are placed and, if successful, must be cancelled after a configurable delay to avoid exhausting test user assets. The development team observed that a short interval between order and cancellation caused issues, prompting the need for delayed cancellation.

Approach

The solution uses java.util.concurrent.DelayQueue, a thread‑safe queue designed for delayed processing. An alternative java.util.Timer was considered but rejected because it creates extra threads and makes rate control harder.

Implementation

A custom class FunDelay implements java.util.concurrent.Delayed to store the order ID and the target execution time. The class provides getDelay and compareTo methods required by the interface.

private static class FunDelay implements Delayed {
    int time;
    String id;
    FunDelay(String id) {
        this.time = getMark() + delay;
        this.id = id;
    }
    @Override
    public long getDelay(TimeUnit unit) {
        return time - getMark();
    }
    @Override
    public int compareTo(Delayed o) {
        FunDelay item = (FunDelay) o;
        return this.time < item.time ? -1 : 1;
    }
}

Test Case

The existing test framework is extended by overriding the after method to handle any remaining order IDs in the delay queue after the test ends. The core tester class FunTester maintains a DelayQueue<FunDelay> and processes due orders in its doing method.

private static class FunTester extends FixedThread<Trade> {
    DelayQueue<FunDelay> ids = new DelayQueue<>();
    FunTester(Trade o, int limit) { super(o, limit, true); }
    @Override
    protected void doing() throws Exception {
        def res = f.order(********);
        if (0 == res.getInteger("code")) {
            def array = res.getJSONArray("data").get(0);
            def id = array.getString("Id");
            ids.add(new FunDelay(id));
        } else {
            output(res.toString());
        }
        int i = 0;
        while (true) {
            if (i++ > 10) break;
            def poll = ids.poll();
            if (poll == null) break;
            f.stop("***", poll.id);
        }
    }
    @Override
    protected void after() {
        super.after();
        sleep(1.0);
        f.clearGrid();
    }
    @Override
    ThreadBase clone() { return new FunTester(f, limit); }
}

Execution

The main method adds a fourth command‑line argument to parameterize the delay time. It initializes the client, parses arguments, creates multiple FunTester tasks, and starts them with a descriptive label.

static int delay;
public static void main(String[] args) {
    ClientManage.init(10, 5, 0, "", 0);
    ArgsUtil util = new ArgsUtil(args);
    int thread = util.getIntOrdefault(0, 1);
    int times = util.getIntOrdefault(1, 1000);
    int runuptime = util.getIntOrdefault(2, 0);
    delay = util.getIntOrdefault(3, 3);
    Constant.RUNUP_TIME = runuptime;
    Common.PRINT_RESPONSE = false;
    Common.VERIFY = false;
    FunLibrary.LOG_KEY = false;
    Common.MOCO = true;
    Common.setHost();
    def line = DataUtils.getMocoTokens();
    def tasks = [];
    thread.times {
        def base = getBase(line.get(getRandomInt(500)));
        def drive = new Trade(base);
        tasks << new FunTester(drive, times);
    }
    new Concurrent(tasks, "下单和延迟10s撤单").start();
    over();
}

Test Result

Using the default 3‑second delay, the log screenshot shows orders starting at 17 s and cancellations beginning at 20 s, confirming that the delayed‑cancellation requirement is satisfied.

Test result screenshot
Test result screenshot
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.

BackendJavaconcurrencyPerformance TestingDelayQueue
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.