Thread-safe irregular rate limiter
Initially, I thought I would need to synchronize everywhere, but in the end, I didn't use any. Is this code still usable from multiple threads?


No. When one thread sets

private ScheduledFuture future;


other may not see it in

    public void waitChoke() throws InterruptedException, ExecutionException {
        if(future == null || future.isDone() || future.isCancelled()) 
            return;
        future.get();
    }


Making future volatile would help. However, there's another problem with it changing before the test and future.get(). Here, a local variable would help.


  As a side question- ScheduledExecutorService seemed like the best way to delay without forcing a block unless something needs to wait, but it asks for a Runnable, which I don't seem to really utilize. Is this poor design?


I guess, it's fine but you've overcomplicated it. Do you need EndThrottle#throttle? Do you need EndThrottle at all?

Why not just this?

future = executor.schedule(new Runnable(), 5, TimeUnit.SECONDS);


Overall, it doesn't look bad, but concerning thread-safety, there may be more problems.