Java capped exponential backoff retry helper

Java
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Supplier;

public final class Retry {
    public static <T> T call(int attempts, long baseMs, long capMs, Supplier<T> task) throws Exception {
        Exception last = null;
        for (int i = 0; i < attempts; i++) {
            try { return task.get(); } catch (Exception e) { last = e; }
            if (i == attempts - 1) break;
            long exp = Math.min(capMs, baseMs << i);
            long sleep = exp / 2 + ThreadLocalRandom.current().nextLong(exp / 2 + 1);
            Thread.sleep(sleep);
        }
        throw last;
    }
}