Java Swing多线程:一个专门用于UI更新的线程池会提高应用程序的性能吗?



目前,我在一个基本的swing应用程序中使用下面的方法,我预计它会变得越来越复杂

public void actionPerformed(ActionEvent e)
{
new Thread(new Runnable()
{
//do heavy db stuff--------------------------------------------
DAO dao = DAO.getInstance();
List<Employees> employeeList = dao.getAllEmployees();
EmployeeModel empModel = new EmployeeModel(employeeList);
SwingUtilities.invokeLater(new Runnable() 
{
public void run()
{
//update swing GUI----------------------------------------
jTableEmployees.setModel(empModel);
}
});
}).start();
}

我已经读了这个答案和答案和准备早因为应用程序将变得越来越复杂。我的策略更新UI的一个大型复杂swing应用正在使用Executor服务,如下所示。

import java.awt.event.ActionEvent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.SwingWorker;
public class SwiftExcecutor {
private final ExecutorService exec = 
Executors.newFixedThreadPool(2);
private class GetEmployeesThread extends SwingWorker<String, String>{
@Override
protected String doInBackground() throws Exception {
return "complete.";
}

@Override
protected void done() {
//Safely update swing components------------------------------
}
}
private class GetContractorsThread extends SwingWorker<String, String>{
@Override
protected String doInBackground() throws Exception {
return "complete.";
}

@Override
protected void done() {
//Safely update swing components------------------------------
}
}
public void actionPerformed(ActionEvent e) {


GetEmployeesThread getAllEmployees = new GetEmployeesThread();
exec.execute(getAllEmployees);

GetContractorsThread getAllContractors = new GetContractorsThread();
exec.execute(getAllContractors);
}    
}

我主要关心的是:

  1. 正在使用专用线程池来更新一个复杂的Swing应用程序声音策略?
  2. 是骨架代码与线程池线程安全?我可以在done()中更新组件吗?方法?如上所示的框架代码?
  3. 我应该期望在UI响应中获得任何性能提升吗?(不是在sql查询和长时间运行的后台任务,我理解这是一个不同的问题在一起)。

从"额外工作"的角度来考虑。创建一个线程比排序一个包含1000个数字的列表(一个"small"的任务)。这比连接到数据库并检索查询结果("大")要便宜得多。Task(如示例中所示)。如果您的应用程序

  • 每当它做小事情时都会启动一个线程,并且花很多时间做小事情…然后它花在线程创建上的时间比做其他事情的时间要多。这对性能不利。
  • 每当它做大事时就会启动一个线程,并且花很多时间做大事…那么线程不是问题的一部分,你应该优化大的东西(也许缓存DB结果以避免不必要的重复查询,优化查询本身,…)。

通过改进一些没有占用大量运行时间的东西(因为你永远不能让它占用负时间,所以你的潜在收益很小),几乎没有什么性能上的提高。

回答你最初的问题:不,你不应该担心应用程序当前状态下的线程池。可伸缩性瓶颈将是对DB的查询(或者输入-输出,如果没有DB支持),而不是线程。

我认为你写的是合理的,它修复了一些问题,创建一个新的线程与重用一个。

swing应用程序的基本结构是。你的UI生成一个事件,在EDT上你决定这个事件是什么动作,然后你在你的事件循环上处理它事件循环可以是一个ExecutorService,它可以是一个字面的while循环,或者它甚至可以只是触发另一个线程。

当您完成事件时,您决定任何更改并将这些更改发布到EDT。

所以我不会说这是"一个用于更新ui的专用线程池"。

你的SwingWorker看起来很好。它们将在后台线程中执行一次,完成后将在EDT上响应。它们对提交给的执行者的类型是不可知的。

使用new Thread();有什么问题

  • 您可以触发许多连续的事件并生成许多完全独立工作的线程。
  • 如果您想以某种方式访问作业,则需要跟踪线程。即中断。
  • 它不提供控制或检查作业是否完成的方法。

这些问题可以通过使用ExecutorService来解决。你唯一没有解决的问题是,如果有人点击按钮两次,你会得到两个任务完全并行地工作。您至少已经将其限制在您的池的大小。

最新更新