在线程之间创建延迟
Creating delay between threads
全部,我有一个被许多线程调用的 api 调用。唯一的问题是延迟下注。线程应至少为 1 秒。我意识到 - w/o 同步块 - 如果一个线程在时间 t1 调用 api,则所有其他线程等待 1 秒,然后所有其他线程在 t1 + 调用 api 1秒。这不是我想要的,所以我把整个等待块放在同步块中,只要一个线程在等待所有其他线程块。
这行得通;但是,我认为这不是最有效的方法。
非常感谢任何建议。
private static volatile AtomicLong lastAPICall = new AtomicLong();
private void callAPI() {
// 1 sec plus a little extra
final long oneMS = 1 * 1000 + 100;
long lastCall = 0;
long timeDiff = 0;
synchronized (lastAPICall) {
timeDiff = System.currentTimeMillis() - lastAPICall.get();
lastCall = lastAPICall.getAndSet(System.currentTimeMillis());
}
}
if (System.currentTimeMillis() - lastCall < oneMS) {
synchronized (lastAPICall) {
try {
long sleep = oneMS - timeDiff;
Thread.sleep(oneMS - timeDiff);
} catch (InterruptedException ignore) {}
finally {
lastAPICall.set(System.currentTimeMillis());
log.info("Thread: " + Thread.currentThread().getId() + " calling the api at this time: " + System.currentTimeMillis());
}
}
}
try {
// API CALL
}
catch (IOException t){
throw t;
} finally {
synchronized (lastAPICall) {
lastAPICall.set(System.currentTimeMillis());
}
}
// Log files for running the code with 4 threads
Thread: 35 calling the api at this time: 1456182353694
Thread: 34 calling the api at this time: 1456182354795
Thread: 37 calling the api at this time: 1456182355905
Thread: 36 calling the api at this time: 1456182357003
如果您想允许以某种费率拨打 API。此外,您不需要带有静态原子的易失性。如果您在同步块中使用它们,则不需要 Atomic。
private static final long MAX_RATE = 1000;
private static final Semaphore API_CALL_SEMAPHORE = new Semaphore(1);
private volatile long lastCall;
public void callApi() throws IOException, InterruptedException {
try {
API_CALL_SEMAPHORE.acquire();
delayedCall();
} catch (IOException | InterruptedException e) {
throw e;
} finally {
API_CALL_SEMAPHORE.release();
}
}
private void delayedCall() throws InterruptedException, IOException {
long tryCallTime = System.currentTimeMillis();
final long deltaTime = tryCallTime - lastCall;
if (deltaTime < MAX_RATE){
final long sleepTime = MAX_RATE - deltaTime;
Thread.sleep(sleepTime);
tryCallTime += sleepTime;
}
// API CALL
lastCall = tryCallTime; // if you want to delay only succeed calls.
}
全部,我有一个被许多线程调用的 api 调用。唯一的问题是延迟下注。线程应至少为 1 秒。我意识到 - w/o 同步块 - 如果一个线程在时间 t1 调用 api,则所有其他线程等待 1 秒,然后所有其他线程在 t1 + 调用 api 1秒。这不是我想要的,所以我把整个等待块放在同步块中,只要一个线程在等待所有其他线程块。
这行得通;但是,我认为这不是最有效的方法。
非常感谢任何建议。
private static volatile AtomicLong lastAPICall = new AtomicLong();
private void callAPI() {
// 1 sec plus a little extra
final long oneMS = 1 * 1000 + 100;
long lastCall = 0;
long timeDiff = 0;
synchronized (lastAPICall) {
timeDiff = System.currentTimeMillis() - lastAPICall.get();
lastCall = lastAPICall.getAndSet(System.currentTimeMillis());
}
}
if (System.currentTimeMillis() - lastCall < oneMS) {
synchronized (lastAPICall) {
try {
long sleep = oneMS - timeDiff;
Thread.sleep(oneMS - timeDiff);
} catch (InterruptedException ignore) {}
finally {
lastAPICall.set(System.currentTimeMillis());
log.info("Thread: " + Thread.currentThread().getId() + " calling the api at this time: " + System.currentTimeMillis());
}
}
}
try {
// API CALL
}
catch (IOException t){
throw t;
} finally {
synchronized (lastAPICall) {
lastAPICall.set(System.currentTimeMillis());
}
}
// Log files for running the code with 4 threads
Thread: 35 calling the api at this time: 1456182353694
Thread: 34 calling the api at this time: 1456182354795
Thread: 37 calling the api at this time: 1456182355905
Thread: 36 calling the api at this time: 1456182357003
如果您想允许以某种费率拨打 API。此外,您不需要带有静态原子的易失性。如果您在同步块中使用它们,则不需要 Atomic。
private static final long MAX_RATE = 1000;
private static final Semaphore API_CALL_SEMAPHORE = new Semaphore(1);
private volatile long lastCall;
public void callApi() throws IOException, InterruptedException {
try {
API_CALL_SEMAPHORE.acquire();
delayedCall();
} catch (IOException | InterruptedException e) {
throw e;
} finally {
API_CALL_SEMAPHORE.release();
}
}
private void delayedCall() throws InterruptedException, IOException {
long tryCallTime = System.currentTimeMillis();
final long deltaTime = tryCallTime - lastCall;
if (deltaTime < MAX_RATE){
final long sleepTime = MAX_RATE - deltaTime;
Thread.sleep(sleepTime);
tryCallTime += sleepTime;
}
// API CALL
lastCall = tryCallTime; // if you want to delay only succeed calls.
}