Backend Development 11 min read

Thread‑Safe Round Robin Load Balancer Using Java AtomicInteger

This article explains how to implement a thread‑safe round‑robin load balancer in Java using AtomicInteger, discusses its advantages and limitations, provides sample code for single‑thread and multithreaded scenarios, and suggests further optimizations such as health checks, weighted routing, and dynamic server updates.

FunTester
FunTester
FunTester
Thread‑Safe Round Robin Load Balancer Using Java AtomicInteger

Load balancing is a key technique for improving performance and availability in distributed systems. The round‑robin algorithm distributes incoming requests sequentially across a list of servers, making it simple and effective when server capacities are similar. This article demonstrates how to build a thread‑safe round‑robin load balancer in Java using AtomicInteger , and applies it to a product‑query scenario for a fictional "XiaoBa" supermarket.

The round‑robin strategy ensures each server receives roughly the same number of requests, which is ideal for environments with stable request volume and homogeneous server capabilities. Its predictable scheduling simplifies debugging and monitoring, and its lightweight implementation reduces development and operational costs.

However, the algorithm cannot sense real‑time server load, cannot handle heterogeneous capacities, and lacks built‑in fault detection. In production, it should be combined with health checks and more sophisticated routing mechanisms.

In a multithreaded context, maintaining a shared index with a plain index++ operation would cause race conditions. AtomicInteger from java.util.concurrent.atomic provides lock‑free atomic operations via CAS, and its getAndUpdate method atomically retrieves the current value and increments it, making it perfect for managing the round‑robin index.

Below is a complete example of a thread‑safe round‑robin load balancer:

package org.funtester.performance.books.chapter05.section6;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * FunTester 轮询负载均衡器示例
 */
public class LoadBalancerDemo {
    private final List
servers; // 服务器列表
    private final AtomicInteger currentIndex; // 当前索引

    public LoadBalancerDemo(List
servers) {
        if (servers == null || servers.isEmpty()) {
            throw new IllegalArgumentException("FunTester: 服务器列表不能为空");
        }
        this.servers = servers;
        this.currentIndex = new AtomicInteger(0);
    }

    public String getServer() {
        int index = currentIndex.getAndUpdate(i -> (i + 1) % servers.size());
        return servers.get(index);
    }

    public static void main(String[] args) {
        List
serverList = List.of("Server1:8081", "Server2:8082", "Server3:8083", "Server4:8084");
        LoadBalancerDemo loadBalancer = new LoadBalancerDemo(serverList);
        System.out.println("FunTester: 模拟轮询负载均衡器");
        for (int i = 0; i < 10; i++) {
            System.out.println("请求 " + (i + 1) + " 分配至: " + loadBalancer.getServer());
        }
    }
}

The code defines a server list, validates it, and uses AtomicInteger.getAndUpdate with a modulo operation to achieve circular distribution. A simple main method prints ten request allocations, demonstrating the round‑robin order.

To evaluate the balancer under high concurrency, the article provides a multithreaded test using ExecutorService and Future objects:

package org.funtester.performance.books.chapter05.section6;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * FunTester 轮询负载均衡器多线程测试
 */
public class RoundRobinLoadBalancer {
    private final List
servers;
    private final AtomicInteger currentIndex;

    public RoundRobinLoadBalancer(List
servers) {
        if (servers == null || servers.isEmpty()) {
            throw new IllegalArgumentException("FunTester: 服务器列表不能为空");
        }
        this.servers = servers;
        this.currentIndex = new AtomicInteger(0);
    }

    public String getServer() {
        int index = currentIndex.getAndUpdate(i -> (i + 1) % servers.size());
        return servers.get(index);
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        List
serverList = List.of("Server1:8081", "Server2:8082", "Server3:8083", "Server4:8084");
        RoundRobinLoadBalancer loadBalancer = new RoundRobinLoadBalancer(serverList);
        ExecutorService executor = Executors.newFixedThreadPool(4);
        List
> futures = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            futures.add(executor.submit(loadBalancer::getServer));
        }
        for (int i = 0; i < futures.size(); i++) {
            System.out.println("请求 " + (i + 1) + " 分配至: " + futures.get(i).get());
        }
        executor.shutdown();
    }
}

This test creates a fixed thread pool of four workers, submits ten concurrent requests, and prints the assigned server for each request. The output shows that even under concurrency the round‑robin order is preserved.

Finally, the article suggests several enhancements: health‑check mechanisms to remove failed nodes, weighted round‑robin to favor more powerful servers, dynamic updates to the server list at runtime, and latency‑based routing to prefer faster nodes. Integrating these features would make the balancer suitable for micro‑service architectures and large‑scale performance testing.

In summary, using AtomicInteger yields a concise, high‑performance, and thread‑safe round‑robin load balancer that can be readily extended with health checks, weighting, and dynamic configuration to meet the demands of modern distributed systems.

backendJavaConcurrencyload balancingRound RobinAtomicInteger
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

login 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.