3

I wanted to build a search that shows you the results when the user finishes writing.

If I had to search in a local db I would have triggered the search every time the user releases a key.

In my case I have to send Web Requests to an API point that exposes the search function. The server allows only 20requests per minute from a single IP.

So, I wrote a Thread that detects when user really finishes writing:

  • (while true)
  • save the searchbox text
  • wait for 400ms
  • check if the searchbox text is the same as the one saved before

Code:

private void checkIfUserFinishedWritingFunction() {
        while(true) {
            String previousText = textField.getText();

        try {
            Thread.sleep(400);
        } catch (InterruptedException ex) {
            return;
        }

        String actualText = textField.getText();

        //WHEN USER FINISHED WRITING...
        if(previousText.equals(actualText)) {
            //IF SEARCHBOX ISN'T EMPTY
            if(!textField.getText().trim().isEmpty()) {
                //START A THREAD THAT SENDS WEB REQUEST
            }
            //IF SEARCHBOX IS EMPTY...
            else {
                //HIDE RESULTS POPUP
                if(resultsList.isShowing())
                    resultsList.hide();
            }
        return;
}}}

NetBeans is telling me that Thread.sleep() called in loop could be dangerous. I think it's because of the cost, and in my the loop runs every 400ms.

How can I fix this algorithm?

user2468425
  • 419
  • 2
  • 13
  • similar--http://stackoverflow.com/questions/14561324/is-it-okay-to-use-thread-sleep-in-a-loop-in-java-to-do-something-at-regular-i – aravind Nov 02 '15 at 12:35
  • IDK, but instead of dedicating a thread to waiting on the clock, you could achieve the same effect by using a timer. – Solomon Slow Nov 02 '15 at 14:31
  • It is not thread-safe to access ui components from any thread other than the event dispatch thread. You should consider using events and a timer. – JimN Nov 03 '15 at 01:48
  • @JimN Thank you, it seems like you were right. I would vote for your comment if I could. – user2468425 Nov 03 '15 at 16:20

2 Answers2

3

I think it's because of the cost, and in my the loop runs every 400ms.

Actually, it is because when you call sleep in a GUI-based application, you are liable to cause the event listener thread to freeze.

(And if this is not on the event listener thread, then calling hide is probably a thread-safety hazard.)

A better alternative would be to use a combination of an event listener for update events on the text box that pays attention to the time since the last query you sent, and something like a ScheduledExecutorService.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thread.sleep() doesn't freeze the ui because it's called in a separated thread. Would you please provide an example? Because I don't get the reason why you would use a ScheduledExecutorService – user2468425 Nov 02 '15 at 18:43
0

Calling Thread.sleep() isn't costly, but creating a thread might be.

As a rule of thumb, if you write code that calls sleep(), then you are either (A) trying to do something that nobody's ever thought of before, or (B) re-inventing something you could have had for free, or (C) making a mistake.

For most of us, it's usually (B) or (C) or both.

In this case, instead of dedicating a thread to polling the GUI state, you could do the polling from within the Event Dispatch Thread (EDT) itself by using a javax.swing.Timer. See the Java tutorials for examples: https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57