6

I think there's probably a name for what I'm describing here, but I don't know it. So my first question would be to know the name of this technique.

Here's an example: suppose you're implementing live search on a web page. Everytime the user types in the search box, you fire a new search query, and the results are updated as often as possible. This is a stupid thing to do because you'll send much more queries than you actually need. Sending a request once per 2-3 letters or at most once per 100 ms is probably sufficient.

A technique is thus to schedule the queries to be executed soon after a key is typed, and if there are still queries that were planned but not executed, cancel them since they're obsolete now.


Now more specifically, are there specific patterns or librairies for solving this problem in Java ?

I had to solve the problem in a Swing app, and I used an ExecutorService, which returned ScheduledFutures that I could cancel. The problem is that I had to manually create a Runnable for each method call I wanted to "buffer", and keep track of each Future to cancel it.

I'm sure I'm not the first person to implement something like this, so there must be a reusable solution somewhere ? Possibly something in Spring with annotations and proxies ?

vgru
  • 49,838
  • 16
  • 120
  • 201
ARRG
  • 2,476
  • 17
  • 28
  • I don't think that you have any pattern. The flow is simple: You run async task 1st time and just set flag = "BUSY" that mean: *don't start next serch till didn't get response on 1st request.* – Maxim Shoustin Sep 10 '13 at 15:38
  • 2
    it is referred to as ***request throttling** –  Sep 10 '13 at 15:40
  • 1
    @JarrodRoberson : thanks, that helped me find some resources. But throttling seems to be slightly different than what I described. With throttling you dispatch requests immediately, and then block newer ones if there are too many requests (earlier requests have priority). The approach I described delays the initial requests so that they can be canceled in case newer ones arrive (later requests have priority). – ARRG Sep 10 '13 at 16:51
  • it is just semantics; block, cancel, delay, whatever. The concept is you manage the rate of requests/transactions explicitly instead of just letting it be a firehose. –  Sep 10 '13 at 16:55
  • I think the word you're looking for is "pacing". See also Nagle's Algorithm for the way it was implemented in TCP to solve a very similar problem with telnet 30 years ago: http://en.wikipedia.org/wiki/Nagle's_algorithm – John Deters Sep 10 '13 at 21:14
  • 1
    @user177800 It's also referred to as debouncing – Kresten Jun 04 '19 at 10:52
  • As ARRG said, debouncing and throttling are different. There are a lot of articles out there explaining the difference visually, like this one https://redd.one/blog/debounce-vs-throttle – SubJunk Dec 27 '21 at 02:43

3 Answers3

13

Given the other answers, and after some searching, it seems there's indeed no library that does what I wanted.

I created one and put it on GitHub. Future readers of this question may find it interesting.

https://github.com/ThomasGirard/JDebounce

I don't think it's very good yet but at least it works and can be used declaratively:

@Debounce(delayMilliseconds = 100)
public void debouncedMethod(int callID, DebounceTest callback) { }
ARRG
  • 2,476
  • 17
  • 28
  • 1
    +1 You should accept this answer instead, it solves the problem and currently is the only Java solution (or one of very few solutions) available online. – vgru Sep 12 '13 at 09:10
1

What you need is called debouncing. You should check the jQuery Throttle/Debounce plugin (which is btw totally independent of jQuery except for using the same namespace). What you need is covered by the debounce part:

Using jQuery throttle / debounce, you can pass a delay and function to $.debounce to get a new function, that when called repetitively, executes the original function just once per “bunch” of calls, effectively coalescing multiple sequential calls into a single execution at either the beginning or end.

Underscore.js has the same method:

_.debounce(function, wait, [immediate]) 

Creates and returns a new debounced version of the passed function which will postpone its execution until after wait milliseconds have elapsed since the last time it was invoked. Useful for implementing behavior that should only happen after the input has stopped arriving. For example: rendering a preview of a Markdown comment, recalculating a layout after the window has stopped being resized, and so on.

// example: debounce layout calculation on window resize
var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);

[Edit]

I mistakenly read "Javascript" instead of Java. Actual Java solution was written by OP afterwards.

Community
  • 1
  • 1
vgru
  • 49,838
  • 16
  • 120
  • 201
  • Thank you. Debouncing is the term I was looking for. I +1ed your answer and will accept it unless someone can give me something more java-specific. – ARRG Sep 11 '13 at 09:00
  • @ARRG: oh crap, I thought it was Javascript (hence these examples). :) – vgru Sep 11 '13 at 09:15
  • Yup, thanks. What I was looking for is support for this in a well maintained library (like _.js or jQuery but in the java world). But I guess this is something that is way more often needed in javascript than in Java. – ARRG Sep 11 '13 at 10:05
  • @ARRG: I use it in C# now and then, like when refreshing related menus and toolbars (e.g. copy/paste) as focus shifts between controls. Don't have a Java implementation though. – vgru Sep 11 '13 at 10:15
1

This is not solvable in Java without using some extra infrastructure like you did with executor and futures. It is not possible to solve this in syntactically concise manner in Java.

You will always need some sort of method result wrapper, because the mechanism returns immediately but the actual result is retrieved later. In your case this was accomplished via Future.

You will always need to be able to specify code to be executed in a manner that will allow delayed execution. In most languages this is accomplished using function pointers or function values or closures. In Java, lacking these language features, this is usually accomplished by passing an object that implements some sort of interface such as Runnable, Callable, that allows delayed execution of a block of code. There are other options but none of them are simple, such as using a dynamic proxy.

tl;dr

Can't do this in concise manner in Java.

RokL
  • 2,663
  • 3
  • 22
  • 26