所以基本上我有一个java应用程序,加速越来越慢(即使我重置了我的JVM)。也没有检测到内存泄漏。操作VM选项到(-Xmx1024m)后,GC工作正常。
无论如何,我试图做的是运行一个带有一些代码的for循环超过40,000次但是它变得越来越慢。
循环是这样的(我必须删除版权问题的SQL查询):
for (int ab = m;ab<=(duration);ab+=600){
jLabel_current.setText(String.valueOf(ab/600));
System.out.println(String.valueOf(ab/600));
System.out.println(String.valueOf(loop));
try{
con = datasource.getConnection();
for (int i=1;i<=4;i++){
String sql=" Some query ";
stmt = con.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
System.out.println(sql);
stmt = con.createStatement();
rs=stmt.executeQuery(sql);
while(rs.next()){
int a =rs.getInt("columnName");
sql="Some query";
pst1=con.prepareStatement(sql);
rs1=pst1.executeQuery();
if(rs1.next()){
x=rs1.getInt("columnName");
for(int b=0;b<x;b++){
if (loop!=max){
int task_id=parseWithDefault((jTable_task_main.getModel().getValueAt(loop, 1).toString()),0);
int jobb_id=parseWithDefault((jTable_task_main.getModel().getValueAt(loop, 4).toString()),0);
int idk=Integer.parseInt(String.valueOf(curTimeinner));
sql="insert into ";
pst2=con.prepareStatement(sql);
pst2.setInt(1, a);
pst2.setInt(2, rs1.getInt("columnName"));
pst2.setInt(3, rs1.getInt("columnName"));
pst2.setInt(4, rs1.getInt("columnName"));
pst2.setInt(5, rs1.getInt("columnName"));
pst2.setDouble(6, rs1.getDouble("columnName"));
pst2.setDouble(7, rs1.getDouble("columnName"));
pst2.setInt(8, rs1.getInt("columnName"));
pst2.setInt(9, rs1.getInt("columnName"));
pst2.setInt(10,n);
pst2.setInt(11,m);
pst2.setInt(12, g);
if(rs1.getLong("columnName")<=curTime){
currDuration=endTask-curTimeinner;
pst2.setLong(13, endTask);
pst2.setLong(14,currDuration );
if(rs.getLong("columnName")>endTask){
currTaskOut="successful";
pst2.setString(15, currTaskOut);
pst2.setInt(16, loop);
}else{
currTaskOut="unsuccessful";
pst2.setString(15, currTaskOut);
pst2.setInt(16, loop);
}
}else {
endTask2=rs1.getLong("columnName")+120;
pst2.setLong(13, endTask2);
pst2.setLong(14, currDuration);
if(rs.getLong("columnName")>endTask2){
currTaskOut="successful";
pst2.setString(15, currTaskOut);
pst2.setInt(16, loop);
}else{
currTaskOut="unsuccessful";
pst2.setString(15, currTaskOut);
pst2.setInt(16, loop);
}
}
pst2.execute();
loop+=1;
if(loop%4==0){
curTimeinner+=600;
String outcome=null;
String out1 = null;
String out2 = null;
String out3 = null;
String out4 = null;
ResultSet rs3=null;
for (int bv = 1; bv <= 4; bv++) {
outcome = "unsuccessful";
String sql1 = "select statment";
pst1 = con.prepareStatement(sql);
rs3 = pst1.executeQuery(sql1);
while (rs3.next()) {
if ("successful".equals(rs3.getString("task_outcome"))) {
outcome = "successful";
}
}
if (bv == 1) {
out1 = outcome;
} else if (bv == 2) {
out2 = outcome;
} else if (bv == 3) {
out3 = outcome;
} else {
out4 = outcome;
sql = "SELECT AUTO_INCREMENT";
pst1 = con.prepareStatement(sql);
rs3 = pst1.executeQuery(sql);
if (rs3.next()) {
res_id = rs3.getInt("AUTO_INCREMENT");
}
if ("successful".equals(out1) && "successful".equals(out2) && "successful".equals(out3) && "successful".equals(out4)) {
sql = "update statment";
pst1 = con.prepareStatement(sql);
pst1.execute();
} else {
sql = "update statment";
pst1 = con.prepareStatement(sql);
pst1.execute();
}
}
}
}
}
}
sql="update statment";
pst=con.prepareStatement(sql);
pst.execute();
}
}
}
curTime += 600;
endTask += 600;
ab+=600;
max+=4;
String sql="update statment";
pst=con.prepareStatement(sql);
pst.execute();
ab-=600;
}
catch (SQLException e ) {
JOptionPane.showMessageDialog(null, e);
} finally {
try { if (rs != null) rs.close(); } catch(Exception e) { }
try { if (stmt != null) stmt.close(); } catch(Exception e) { }
try { if (con != null) con.close(); } catch(Exception e) { }
try { if (pst != null) pst.close(); } catch(Exception e) { }
try { if (rs1 != null) rs1.close(); } catch(Exception e) { }
try { if (pst1 != null) pst1.close(); } catch(Exception e) { }
try { if (rs2 != null) rs2.close(); } catch(Exception e) { }
try { if (pst2 != null) pst2.close(); } catch(Exception e) { }
}
}
这是堆转储:
Java2D Disposer" daemon prio=10 tid=10 WAITING
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:142)
Local Variable: java.lang.ref.ReferenceQueue#72
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:158)
at sun.java2d.Disposer.run(Disposer.java:148)
Local Variable: sun.java2d.Disposer#1
at java.lang.Thread.run(Thread.java:745)
"SwingWorker-pool-1-thread-1" daemon prio=5 tid=21 WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Thread.java:1245)
at java.lang.Thread.join(Thread.java:1319)
at simulator.Main_panel$simulation1.doInBackground(Main_panel.java:896)
at simulator.Main_panel$simulation1.doInBackground(Main_panel.java:876)
at javax.swing.SwingWorker$1.call(SwingWorker.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
Local Variable: javax.swing.SwingWorker$2#1
Local Variable: javax.swing.SwingWorker$1#1
at javax.swing.SwingWorker.run(SwingWorker.java:334)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
Local Variable: java.util.concurrent.ThreadPoolExecutor#1
Local Variable: simulator.Main_panel$simulation1#1
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
Local Variable: java.util.concurrent.ThreadPoolExecutor$Worker#1
at java.lang.Thread.run(Thread.java:745)
"*** Profiler Agent Special Execution Thread 6" daemon prio=5 tid=26 WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at org.netbeans.lib.profiler.server.ProfilerServer$SeparateCmdExecutionThread.run(ProfilerServer.java:289)
"*** JFluid Monitor thread ***" daemon prio=10 tid=25 TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at org.netbeans.lib.profiler.server.Monitors$SurvGenAndThreadsMonitor.run(Monitors.java:186)
"Signal Dispatcher" daemon prio=9 tid=4 RUNNABLE
"TimerQueue" daemon prio=5 tid=20 TIMED_WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
Local Variable: java.util.concurrent.locks.AbstractQueuedSynchronizer$Node#8
Local Variable: java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject#3
at java.util.concurrent.DelayQueue.take(DelayQueue.java:223)
Local Variable: java.util.concurrent.locks.ReentrantLock#77
Local Variable: java.util.concurrent.DelayQueue#1
at javax.swing.TimerQueue.run(TimerQueue.java:171)
Local Variable: javax.swing.TimerQueue#1
at java.lang.Thread.run(Thread.java:745)
"Attach Listener" daemon prio=5 tid=5 RUNNABLE
"Reference Handler" daemon prio=10 tid=2 WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)
"Thread-1" prio=5 tid=14 RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:150)
Local Variable: java.net.SocketInputStream#1
Local Variable: java.io.FileDescriptor#8
Local Variable: byte[]#472
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114)
at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161)
at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189)
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2549)
Local Variable: com.mysql.jdbc.util.ReadAheadInputStream#1
Local Variable: byte[]#464
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3002)
Local Variable: com.mysql.jdbc.Buffer#2
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2991)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3532)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)
Local Variable: com.mysql.jdbc.MysqlIO#1
Local Variable: java.lang.String#287058
Local Variable: com.mysql.jdbc.Buffer#1
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2618)
Local Variable: java.lang.String#286257
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568)
at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1557)
Local Variable: com.mysql.jdbc.StatementImpl#2
Local Variable: com.mysql.jdbc.JDBC4Connection#1
at org.apache.commons.dbcp2.DelegatingStatement.executeQuery(DelegatingStatement.java:207)
Local Variable: org.apache.commons.dbcp2.DelegatingStatement#3
at org.apache.commons.dbcp2.DelegatingStatement.executeQuery(DelegatingStatement.java:207)
Local Variable: org.apache.commons.dbcp2.DelegatingStatement#4
at simulator.Main_panel$2.run(Main_panel.java:1011)
Local Variable: java.lang.String#346303
Local Variable: java.lang.String#751527
"AWT-Shutdown" prio=5 tid=11 WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at sun.awt.AWTAutoShutdown.run(AWTAutoShutdown.java:295)
Local Variable: sun.awt.AWTAutoShutdown#1
at java.lang.Thread.run(Thread.java:745)
"Finalizer" daemon prio=8 tid=3 WAITING
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:142)
Local Variable: java.lang.ref.ReferenceQueue#82
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:158)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
Local Variable: java.lang.System$2#1
"AWT-Windows" daemon prio=6 tid=12 RUNNABLE
at sun.awt.windows.WToolkit.eventLoop(Native Method)
at sun.awt.windows.WToolkit.run(WToolkit.java:303)
Local Variable: sun.awt.windows.WToolkit#1
at java.lang.Thread.run(Thread.java:745)
"DestroyJavaVM" prio=5 tid=19 RUNNABLE
"AWT-EventQueue-0" prio=6 tid=16 WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
Local Variable: java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject#2
Local Variable: java.util.concurrent.locks.AbstractQueuedSynchronizer$Node#4
at java.awt.EventQueue.getNextEvent(EventQueue.java:542)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:170)
Local Variable: java.awt.EventQueue#1
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
Local Variable: java.awt.EventDispatchThread$HierarchyEventFilter#1
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
Local Variable: java.awt.EventDispatchThread$1#1
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
"*** Profiler Agent Communication Thread" daemon prio=10 tid=24 RUNNABLE
at sun.management.HotSpotDiagnostic.dumpHeap0(Native Method)
at sun.management.HotSpotDiagnostic.dumpHeap(HotSpotDiagnostic.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
Local Variable: sun.management.HotSpotDiagnostic#2
Local Variable: sun.reflect.NativeMethodAccessorImpl#10
Local Variable: java.lang.Object[]#262773
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.netbeans.lib.profiler.server.system.HeapDump.takeHeapDump16(HeapDump.java:165)
Local Variable: java.lang.String#751526
at org.netbeans.lib.profiler.server.system.HeapDump.takeHeapDump(HeapDump.java:92)
at org.netbeans.lib.profiler.server.ProfilerServer.handleClientCommand(ProfilerServer.java:1657)
at org.netbeans.lib.profiler.server.ProfilerServer.listenToClient(ProfilerServer.java:1733)
Local Variable: org.netbeans.lib.profiler.wireprotocol.TakeHeapDumpCommand#1
at org.netbeans.lib.profiler.server.ProfilerServer.run(ProfilerServer.java:690)
答案 0 :(得分:0)
它充满了资源泄漏,主要是因为将变量重用于另一个对象实例,因此没有关闭先前的实例。
将变量声明为接近其首次使用并使用 try-with-resources :
String sql1 = "..."
try (PreparedStatement pst1 = con.prepareStatement(sql1)) {
for (int a = 0; a < 100; ++a) {
pst1.setInt(1, a);
try (ResultSet rs1 = pst1.executeQuery()) {
while (rs1.next()) {
}
} // Safe close of rs1
}
} // Safe close of pst1
为了接收生成的主键,AUTO_INCR列,java设计了一个独立于供应商的机制:
String sql1 = "INSERT INTO table(col2, col3) VALUES(?, ?)";
try (PreparedStatement pst1 = con.prepareStatement(sql1, Statement.RETURN_GENERATED_KEYS))) {
int updateCount = pst1.executeUpdate();
if (updateCount != 0) { // Records inserted?
int res_id = 0; // Key
try (ResultSet generatedKeysRS = pst1.getGeneratedKeys()) {
if (generatedKeysRS.next()) {
res_id = generatedKeysRS.getInt(1);
}
}
}
}
当两个插入同时发生并且生成新生成的密钥时,这解决了并发问题:
1. A inserts
2. B inserts
3. B asks generated key
4. A asks generated key
请允许我指出两个最佳做法:
代码太长,像rs1 / rs2 / rs3这样的编号会将代码暴露给混淆。尝试介绍功能。给出有意义的名字。
相同的防御性编码:不要在if语句中设置 i th 列:
int endTask = 0;
int currDuration = 0;
String currTaskOut = "";
if (rs1.getLong("columnName") <= curTime) {
//if (rs.getLong("columnName") > ...) {
endTask = ...;
currDuration = ...;
} else {
//...
}
pst2.setLong(13, endTask);
pst2.setLong(14, currDuration);
pst2.setString(15, currTaskOut);
pst2.setInt(16, loop);