Java 调用数据库时,应用程序处于冻结状态
我在Java的Java 调用数据库时,应用程序处于冻结状态,java,mysql,multithreading,swing,freeze,Java,Mysql,Multithreading,Swing,Freeze,我在Java的ComponentAdapter中实现了很多东西。由于它从数据库加载数据并在JTable中显示,所以我将其添加到另一个线程中。我将向您展示这样的ComponentAdapter private class DisplayInitialRevenue_Thread implements Runnable { @Override public void run() { displayInitialRe
ComponentAdapter
中实现了很多东西。由于它从数据库加载数据并在JTable
中显示,所以我将其添加到另一个线程中。我将向您展示这样的ComponentAdapter
private class DisplayInitialRevenue_Thread implements Runnable
{
@Override
public void run()
{
displayInitialRevenue_Method();
}
}
private void displayInitialRevenue_Method()
{
//Get the dates from the combo
String selectedCouple = revenueYearCombo.getSelectedItem().toString();
if(selectedCouple.equals("Select Year"))
{
return;
}
String[] split = selectedCouple.split("/");
//Related to DB
double totalamountInvested;
//Get data from the database
dbConnector = new DBHandler();
dbConnector.makeConnection();
DefaultTableModel model = (DefaultTableModel) initialRevenueTable.getModel();
model.setRowCount(0);
ResultSet selectAllDetails = dbConnector.selectAllDetails("SQL CODE HERE ");
try
{
if(selectAllDetails.isBeforeFirst()==false)
{
JOptionPane.showMessageDialog(null,"This table is empty");
}
else
{
while(selectAllDetails.next())
{
String clientName = selectAllDetails.getString("Client Name");
String providerName = selectAllDetails.getString("Provider Name");
Double amountInvested = selectAllDetails.getDouble("Invest_Amount");
//Get Other Data
//Update the table
Object[]row = {dateS,clientName,providerName,amountInvested};
model.addRow(row);
//Get the total
amountInvested = amountInvested+amountInvested;
}
//Add the sum
Object[]blankRow = {null,null,null,null};
model.addRow(blankRow);
Object[]row = {dateS,clientName,providerName,amountInvested};
}
}
catch(SQLException sql)
{
JOptionPane.showMessageDialog(null,sql.getLocalizedMessage());
}
}
并且,可以通过3种方式调用上述线程。这是通过ItemListener
附加到JComboBox
,ActionListener
附加到JMenu
和ComponentListener
实现的
组件侦听器
private class DisplayInitialRevenue extends ComponentAdapter
{
public void componentShown(ComponentEvent e)
{
formMemorizer = FormMemorizer.Initial_Revenue;
//displayInitialRevenue_Method();
DisplayInitialRevenue_Thread t = new DisplayInitialRevenue_Thread();
t.run();
}
}
private class RevenueYearComboAction implements ItemListener
{
@Override
public void itemStateChanged(ItemEvent e)
{
if(e.getStateChange() == ItemEvent.SELECTED)
{
int selection = formMemorizer;
if(selection==-1)
{
return;
}
else if(selection==FormMemorizer.Initial_Revenue)
{
//displayInitialRevenue_Method();
DisplayInitialRevenue_Thread t = new DisplayInitialRevenue_Thread();
t.run();
}
}
}
ItemListener
private class DisplayInitialRevenue extends ComponentAdapter
{
public void componentShown(ComponentEvent e)
{
formMemorizer = FormMemorizer.Initial_Revenue;
//displayInitialRevenue_Method();
DisplayInitialRevenue_Thread t = new DisplayInitialRevenue_Thread();
t.run();
}
}
private class RevenueYearComboAction implements ItemListener
{
@Override
public void itemStateChanged(ItemEvent e)
{
if(e.getStateChange() == ItemEvent.SELECTED)
{
int selection = formMemorizer;
if(selection==-1)
{
return;
}
else if(selection==FormMemorizer.Initial_Revenue)
{
//displayInitialRevenue_Method();
DisplayInitialRevenue_Thread t = new DisplayInitialRevenue_Thread();
t.run();
}
}
}
我有很多这样的方法从数据库中获取数据,向JTables提供数据,从GUI中获取数据并保存在数据库中
现在我的问题是,每当数据库调用发生时,所有这些都会冻结。我以为是bcs的线程问题,所以我做了上面的DisplayInitialRevenue\u线程
来调用DisplayInitialRevenue\u方法()
。然后我只调用了与调用此方法相关的区域,但它有时仍然冻结!我的其他数据库方法不在单独的线程中,但这是一个方法,所以为什么甚至调用“only”这个方法都会导致冻结?它在一根线里
顺便说一句,我使用的是Java 8,使用的是MySQL服务器版本:5.6.16-MySQL社区服务器(GPL),它随XAMPP一起提供。调用t.start()
来启动一个新的线程,调用Thread#run
除了在同一线程上下文中调用Thread
的run
方法外,什么都不做
话虽如此,Swing不是线程安全的,Swing要求对UI的所有更新都是在事件调度线程的上下文中进行的。代替使用<代码>线程< /代码>,您应该考虑使用<代码> SaveWorks,它允许您在后台线程中执行长时间运行的任务,但它提供了易于使用的<代码>发布< //>代码>进程> <代码>方法,并在完成时调用<代码>完成< /代码>,在EDT的上下文中为您执行
有关更多详细信息,请参见请查看它冻结的位置,是否使用了一些JProfiler,如何使用,从何处输出,但说明谈论阻止EDT,:-)Oracle教程-事件调度线程,我的建议是不要在生产代码中使用SwingWorker,投票也一样结束broad@mKorbel:在下面的一个答案中,答案是使用SwingWorker
@mKorbel:我无法指出任何地方,冻结只会“有时”发生,而且会“在任何时候”调用DB。这意味着,有很多表单需要编辑、更新和查看数据库中的记录,使用任何此类表单都可能导致“有时”冻结这些记录。@mKorbelt.run()
.“请给我更多建议”-不要做你正在做的事,使用SwingWorker
。您可能希望有一个通读版本,它将使人们更容易阅读您的代码,您也更容易阅读其他代码:-)不要使用SwingWorker for JDBC,它是为enjoy@mKorbel为什么?通过一些调整(附加通知),我发现它实际上相当有用;)-添加一个ExecutorService
,它会大大降低痛苦阈值…@MadProgrammer:想象一下我正在使用t.start()
移动。有些人告诉我“不要使用其他线程更新GUI”?@sniper所有对UI的更新都需要与EDT的上下文同步执行,如果你不想使用SwingWorker
,你需要使用SwingUtilities.invokeLater
,这将突出我推荐SwingWorker
的原因