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

3
我希望建立一个搜索功能,当用户输入完成后,即可显示结果。
如果我要在本地软件库中进行搜索,我会每次用户释放按键时触发搜索。
在我的情况下,我需要向公开搜索功能的API点发送Web请求。该服务器每分钟仅允许来自单个IP的20个请求。
因此,我编写了一个线程来检测用户何时真正完成写作:
- (while true) - 保存搜索框的文本 - 等待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毫秒运行一次。

我该如何修复这个算法?


similar--https://dev59.com/3WUq5IYBdhLWcg3wXvMC - aravind
我不知道,但是你可以通过使用定时器来实现相同的效果,而不是专门为等待时钟分配一个线程。 - Solomon Slow
访问UI组件时,除了事件分派线程之外的任何线程都不是线程安全的。您应该考虑使用事件和计时器。 - JimN
@JimN 谢谢,看来你是对的。如果可以的话,我会投票支持你的评论。 - user2468425
2个回答

3
我认为这是因为成本问题,而且在我的循环中每400毫秒运行一次。
实际上,当你在基于GUI的应用程序中调用sleep时,你可能会导致事件监听线程冻结。
(如果这不是在事件监听线程上,那么调用hide可能会导致线程安全隐患。)
更好的替代方法是使用一个事件监听器来更新文本框上的事件,并注意自上次发送查询以来的时间,以及类似于ScheduledExecutorService的东西。

Thread.sleep()不会冻结UI,因为它在一个单独的线程中被调用。您能否提供一个例子?因为我不明白为什么要使用ScheduledExecutorService。 - user2468425

0

调用Thread.sleep()不会太耗费资源,但创建线程可能会。

一般来说,如果你编写的代码需要调用sleep(),那么你要么是在尝试做一些前人从未考虑过的事情,要么是在重新发明已经有现成解决方案的东西,或者是在犯错误。

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

在这种情况下,你可以使用javax.swing.Timer从事件分派线程(EDT)中进行轮询,而不需要专门为此创建一个线程。请参阅Java教程以获取示例:https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接