用Java实现去抖动

对于我正在编写的某些代码,我可以使用debounceJava中的一个不错的通用实现。

public interface Callback {

public void call(Object arg);

}

class Debouncer implements Callback {

public Debouncer(Callback c, int interval) { ... }

public void call(Object arg) {

// should forward calls with the same arguments to the callback c

// but batch multiple calls inside `interval` to a single one

}

}

call()被称为多次interval毫秒具有相同参数的回调函数应调用一次。

可视化:

Debouncer#call  xxx   x xxxxxxx        xxxxxxxxxxxxxxx

Callback#call x x x (interval is 2)

  • (某种程度上)这已经在某些Java标准库中存在了吗?
  • 您将如何实施?

回答:

请考虑以下线程安全解决方案。请注意,锁定粒度是在密钥级别上的,因此仅同一密钥上的调用会相互阻塞。它还处理在调用call(K)时发生的密钥K过期的情况。

public class Debouncer <T> {

private final ScheduledExecutorService sched = Executors.newScheduledThreadPool(1);

private final ConcurrentHashMap<T, TimerTask> delayedMap = new ConcurrentHashMap<T, TimerTask>();

private final Callback<T> callback;

private final int interval;

public Debouncer(Callback<T> c, int interval) {

this.callback = c;

this.interval = interval;

}

public void call(T key) {

TimerTask task = new TimerTask(key);

TimerTask prev;

do {

prev = delayedMap.putIfAbsent(key, task);

if (prev == null)

sched.schedule(task, interval, TimeUnit.MILLISECONDS);

} while (prev != null && !prev.extend()); // Exit only if new task was added to map, or existing task was extended successfully

}

public void terminate() {

sched.shutdownNow();

}

// The task that wakes up when the wait time elapses

private class TimerTask implements Runnable {

private final T key;

private long dueTime;

private final Object lock = new Object();

public TimerTask(T key) {

this.key = key;

extend();

}

public boolean extend() {

synchronized (lock) {

if (dueTime < 0) // Task has been shutdown

return false;

dueTime = System.currentTimeMillis() + interval;

return true;

}

}

public void run() {

synchronized (lock) {

long remaining = dueTime - System.currentTimeMillis();

if (remaining > 0) { // Re-schedule task

sched.schedule(this, remaining, TimeUnit.MILLISECONDS);

} else { // Mark as terminated and invoke callback

dueTime = -1;

try {

callback.call(key);

} finally {

delayedMap.remove(key);

}

}

}

}

}

以上是 用Java实现去抖动 的全部内容, 来源链接: utcz.com/qa/426342.html

回到顶部