我想构建一个搜索,在用户完成写作时向您显示结果。
如果我必须在本地数据库中搜索,我会在每次用户释放密钥时触发搜索。
在我的情况下,我必须将Web请求发送到公开搜索功能的API点。服务器每个分钟只允许每分钟20次请求。
所以,我编写了一个Thread,用于检测用户何时完成写作:
代码:
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毫秒运行一次。
如何修复此算法?
答案 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