在SWING/Java中使用线程的最佳实践

3
我有一个SWING UI,其中包含一个按钮,用于创建一个新的SwingWorker线程。该线程然后查询SQLite数据库以获取结果并将其放入JTable中。在我的StringWorker构造函数中,参数是从其他SWING组件(如JSpinner,JComboBoxes等)中取出的各种字段。
由于我对所有这些线程事物都很陌生,我想向更有经验的程序员寻求一些建议,了解我应该如何做才能实现我的目标。
  1. 我想知道当我使用System.exit(0);关闭程序时,线程是否会自动结束,以免出现内存泄漏。

  2. 最好的方法是什么,以确保我没有两个线程同时访问我的数据库(假设用户多次单击按钮或者管理员正在使用一些文件更新数据库(在我的程序中),那么当第一个线程解析文件并更新数据库时,他想要使用按钮查询数据库,等等)。

  3. 使用线程会变慢吗?起初,我在EDT中正确计算了所有内容,当然,在按下按钮后,UI每次都会锁定,但如果我记得正确,它只锁定了大约5秒钟。现在,当我按下按钮时,它不会锁定,但似乎结果需要比在JTable中显示少一点的时间。这是因为我在代码中犯了一个错误,还是这是正常的?

我考虑在查询所在的类中使用静态字段,并将其设置为true,如果正在使用,则不管哪个线程正在使用数据库,第二个线程都不会启动。这样做的方式正确吗?

1
  1. 当工作线程正在运行时禁用按钮,一旦工作线程完成后再启用按钮。
- Sam Barnum
@Sam Barnum,好主意,我没想到。 - Jumbala
与其长篇解释你如何编写代码,不如在这里发布相关的片段?如果你想得到有用的反馈,那样会更好。 - jfpoilpret
@jfpoilpret 我没有发布代码片段,因为我觉得它并不相关,因为我是在一般情况下寻求帮助。除了我描述的示例之外,还有其他使用线程的情况,我只是想看看我是否在正确的轨道上,在创建我需要的所有线程之前。 - Jumbala
@Adam 我问这个问题是因为你的第三点可能与你的代码有关,如果没有看到你的 SwingWorker 代码,很难说清楚。 - jfpoilpret
@jfpoilpret 我明白了...如果我弄不清楚为什么它变慢,我会尝试制作一个简化的示例...不过我有一个想法为什么会这样。谢谢! - Jumbala
2个回答

3

我想知道当我用 System.exit(0); 关闭程序时,线程是否会自动结束?

是的。整个进程以及属于该进程的线程都会结束。但是,如果你不调用 System.exit(),所有非守护线程必须在进程消失之前完成。

保证我没有两个线程同时访问数据库的最佳方法是什么?

由于这是一个 Swing 应用程序,我假设你和管理员不能同时访问应用程序。但是,为了确保即使在单个应用程序中,你也无法启动更多影响数据库的操作,你必须阻止 UI。要么禁用按钮,要么将玻璃窗格放在 UI 上面。模态进度对话框也很有帮助。

使用线程会使速度变慢吗?

不会,如果正确使用,速度不会变慢。慢操作需要花费一样长的时间。你不能通过线程修复它,但是你可以,在提供漂亮、非阻塞 UI 的同时保持速度(感知)相同,或者你可以同时执行多个慢操作,从而增加感知速度。


3
  1. 如果没有必要(通常不需要),请勿在代码中使用 System#exit。这里有一些解释为什么以及应该使用什么。

  2. 您的数据库可以处理两个并发请求,所以本身并不是坏事。如果您使用JDBC及其通过DataSource池化的连接,则应该将一个这样的连接的使用限制为一次只能由一个线程使用。为了解决重复数据库查询的问题,例如“点击两次”的情况,可能有多种解决方案。我在这里假设您的场景是:您有一个分布到多个人的Swing UI,每个实例都与同一个数据库交互 -> 只需在执行数据库查询期间禁用按钮即可。

  3. 如果不直接在事件调度线程中运行代码,由于工作线程的调度,速度会稍微慢一点,但这应该不会被注意到。要查看出错的原因,我需要看到相关的代码。


谢谢你的解释,我会检查一下我的代码,看看如何改进它。目前,我只是在本地进行测试,所以多个连接并不是问题,因为它处于“信息亭”环境的测试模式中。最终,我将设置多个信息亭,并且它们将使用同一个数据库。不过,我不知道DataSource是什么,但我会去了解一下。我正在使用SQLite,但如果最终将数据库设置在我的网站上,可能会改用MySQL,所以现在不确定这是否相关,因为我不知道它是什么。 - Jumbala
DataSource是用于使用JDBC连接到数据库的工具。 - emboss
哦,看起来我正在使用相同的方法,只是我不知道它被称为那个... 我使用Connection conn = DriverManager.getConnection("jdbc:sqlite:database.sqlite")。非常感谢您的输入,我相信它会大大改善我的程序。 - Jumbala

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