检测用户何时完成写入 - 在循环中调用Thread.sleep()

时间:2015-11-02 12:28:15

标签: java multithreading while-loop thread-sleep search-box

我想构建一个搜索,在用户完成写作时向您显示结果。

如果我必须在本地数据库中搜索,我会在每次用户释放密钥时触发搜索。

在我的情况下,我必须将Web请求发送到公开搜索功能的API点。服务器每个分钟只允许每分钟20次请求。

所以,我编写了一个Thread,用于检测用户何时完成写作:

  • (虽然如此)
  • 保存搜索框文字
  • 等待400毫秒
  • 检查搜索框文本是否与之前保存的文本相同

代码:

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告诉我在循环中调用的Thread.sleep()可能很危险。我认为这是因为成本,而且我的循环每400毫秒运行一次。

如何修复此算法?

2 个答案:

答案 0 :(得分:3)

  

我认为这是因为成本,而且我的循环每400毫秒运行一次。

实际上,这是因为当您在基于GUI的应用程序中调用sleep时,您可能会导致事件侦听器线程冻结。

(如果这不在事件监听器线程上,那么调用hide可能是线程安全隐患。)

更好的选择是在文本框上使用事件监听器组合更新事件,注意自上次发送查询以来的时间,以及类似ScheduledExecutorService的内容。

答案 1 :(得分:0)

调用Thread.sleep()并不昂贵,但创建一个线程可能是。

根据经验,如果您编写的代码调用sleep(),那么您要么(A)尝试做一些以前没有人想过的事情,要么(B)重新发明一些你可能拥有的东西是免费的,或(C)犯了错误。

对于我们大多数人来说,通常是(B)或(C)或两者兼而有之。

在这种情况下,您可以使用javax.swing.Timer从事件调度线程(EDT)本身进行轮询,而不是将线程专用于轮询GUI状态。有关示例,请参阅Java教程:https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html