Java线程操作MySQL出现连接数过多及空指针异常该如何解决
错误根因
- 连接过多报错:
- 线程run方法中重复创建
VentanaAdministrador实例,新实例初始化时又会启动新的填充线程,陷入无限循环创建实例、创建数据库连接的逻辑,很快就把MySQL的连接数占满 - 所有JDBC资源(Connection、PreparedStatement、ResultSet)使用后未主动释放,连接长期占用不回收
- 线程run方法中重复创建
- 空指针报错:
- Swing是单线程UI框架,你直接在子线程中操作JTable、TableModel等UI组件,不符合Swing线程安全规则,很容易触发空指针
- 若数据库连接获取失败,
getConnection会返回null,代码未判空直接调用prepareStatement方法会直接抛出空指针 - 无限创建的
VentanaAdministrador实例还未执行完initComponents初始化组件逻辑,就尝试操作TablaVentanaAsignar组件也会触发空指针
修复方案
窗口启动自动填充表格的需求可以正常实现,只要修正线程逻辑和资源处理规则即可,具体修改点如下:
- 移除线程内创建
VentanaAdministrador实例的逻辑,直接调用当前类的连接获取方法 - 使用try-with-resources语法自动释放JDBC资源,无需手动关连接
- 所有UI更新逻辑包裹在
SwingUtilities.invokeLater中,确保在Swing事件调度线程执行 - 增加空值判断,避免空指针,同时修正原配置中
autoReconnet的拼写错误
修正后的代码
import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.sql.*; public class VentanaAdministrador extends javax.swing.JFrame{ public static final String URL = "jdbc:mysql://localhost:3306/floreria?autoReconnect=true&useSSL=false"; public static final String Usuario = "root"; public static final String Contraseña = ""; public Connection getConnection(){ Connection conexion = null; try{ Class.forName("com.mysql.jdbc.Driver"); conexion = DriverManager.getConnection(URL,Usuario,Contraseña); }catch(Exception ex){ System.err.println("连接获取失败: "+ex); } return conexion; } Thread llenado = new Thread(){ public void run(){ // 先在子线程拉取数据,避免阻塞UI DefaultTableModel modeloTabla = new DefaultTableModel(); modeloTabla.addColumn("No. Empleado"); modeloTabla.addColumn("Nombre"); modeloTabla.addColumn("Sucursal"); modeloTabla.addColumn("Tiempo trabajado"); // try-with-resources自动关闭连接、Statement、结果集 try(Connection conexion = getConnection(); PreparedStatement ps = conexion.prepareStatement("select NumeroEmpleado,Nombre,Punto_de_venta,TiempoTrabajo from empleados where Puesto=?")){ if(conexion == null){ System.err.println("数据库连接为空,终止加载"); return; } ps.setString(1, "Diseñador"); try(ResultSet rs = ps.executeQuery()){ while(rs.next()){ Object fila[] = new Object[4]; fila[0] = rs.getObject(1); fila[1] = rs.getObject(2); fila[2] = rs.getObject(3); fila[3] = rs.getObject(4); modeloTabla.addRow(fila); } } // UI更新放到Swing事件调度线程执行,保证线程安全 SwingUtilities.invokeLater(() -> { TablaVentanaAsignar.setModel(modeloTabla); }); }catch(Exception ex){ System.err.println("加载数据出错: "+ex); } } }; public VentanaAdministrador() { initComponents(); llenado.start(); } // 其余原有代码保持不变 }
内容的提问来源于stack exchange,提问作者Mario Garcia
相关产品推荐
相关产品推荐

