先来看我的线程
private DataHandle dh = new DataHandle();public synchronized void runTask() {
try {
dh.handle(pbean.getStartNo(), pbean.getEndNo()); } catch (Exception e) {
e.printStackTrace();
// TaskManagerBean.returnItem();
}这个是我的线程,里面用到一个叫DataHandle的类,现在来看这个DataHandle的类public synchronized void handle(String start, String end) { Statement stmt = null;
ResultSet rs = null;
StringBuffer sb = new StringBuffer();
try {
if (conn != null) { sb.append("select tid,tname,description,dbvalue,xmlvalue");
sb.append(" from exporttable limit " + start + "," + end);
System.out.println("sql===" + sb.toString());
stmt = conn.createStatement();
rs = stmt.executeQuery(sb.toString());
while (rs.next()) {
db = new DataBean();
db.setTname(StringUtil.replaceNull(rs
.getString("tname")));
db.setDescription(StringUtil.replaceNull(rs
.getString("description")));
db.setDbValue(StringUtil.replaceNull(rs
.getString("dbvalue")));
db.setXmlValue(StringUtil.replaceNull(rs
.getString("xmlvalue")));
/* resultList.add(db); */
// dealing(db);
}
/* return resultList; */ }
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
rs.close();
rs = null;
} catch (Exception e) {
}
try {
stmt.close();
stmt = null; } catch (Exception e) {
}
try {
conn.close();
conn = null;
} catch (Exception e) {
}
}
}这个类里有一个handle方法这个线程是这样运行的,5个线程第一个线程取0-100条记录
第二个线程取100-200条记录
第三个线程取200-300条记录
.
.
.
依此类推,现在的问题时,程序在运行时经常出现:resultset have been closed这样的问题经分析,是因为5个线程中,每个线程都有操作DataHandle的类,那么内存中就有5个DataHandle类,每个类中由于都进行resultset的打开,因此在运行时,
会发生一个线程中的ResultSet还在被操作时,已经被另一个线程中的ResultSet关闭的情况我试过了
在DataHandle中Synchronized(rs),synchronized(stmt),甚至我的方法大家都看到了,都是synchronized的,为什么还会发生这样的事,大家有没有好的解决方法多说一句,每个DataHandle中打开一个connection,然后操作完100条数据后关闭,因此始终是存在5个线程,5个connection,5个resultset.还是我的设计上有问题,我的设计就想是
多个线程,同时读数据库,只不过是每个线程读不同的数据块,就像我前面提到过的一样,0-100,100-200这样读的.
private DataHandle dh = new DataHandle();public synchronized void runTask() {
try {
dh.handle(pbean.getStartNo(), pbean.getEndNo()); } catch (Exception e) {
e.printStackTrace();
// TaskManagerBean.returnItem();
}这个是我的线程,里面用到一个叫DataHandle的类,现在来看这个DataHandle的类public synchronized void handle(String start, String end) { Statement stmt = null;
ResultSet rs = null;
StringBuffer sb = new StringBuffer();
try {
if (conn != null) { sb.append("select tid,tname,description,dbvalue,xmlvalue");
sb.append(" from exporttable limit " + start + "," + end);
System.out.println("sql===" + sb.toString());
stmt = conn.createStatement();
rs = stmt.executeQuery(sb.toString());
while (rs.next()) {
db = new DataBean();
db.setTname(StringUtil.replaceNull(rs
.getString("tname")));
db.setDescription(StringUtil.replaceNull(rs
.getString("description")));
db.setDbValue(StringUtil.replaceNull(rs
.getString("dbvalue")));
db.setXmlValue(StringUtil.replaceNull(rs
.getString("xmlvalue")));
/* resultList.add(db); */
// dealing(db);
}
/* return resultList; */ }
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
rs.close();
rs = null;
} catch (Exception e) {
}
try {
stmt.close();
stmt = null; } catch (Exception e) {
}
try {
conn.close();
conn = null;
} catch (Exception e) {
}
}
}这个类里有一个handle方法这个线程是这样运行的,5个线程第一个线程取0-100条记录
第二个线程取100-200条记录
第三个线程取200-300条记录
.
.
.
依此类推,现在的问题时,程序在运行时经常出现:resultset have been closed这样的问题经分析,是因为5个线程中,每个线程都有操作DataHandle的类,那么内存中就有5个DataHandle类,每个类中由于都进行resultset的打开,因此在运行时,
会发生一个线程中的ResultSet还在被操作时,已经被另一个线程中的ResultSet关闭的情况我试过了
在DataHandle中Synchronized(rs),synchronized(stmt),甚至我的方法大家都看到了,都是synchronized的,为什么还会发生这样的事,大家有没有好的解决方法多说一句,每个DataHandle中打开一个connection,然后操作完100条数据后关闭,因此始终是存在5个线程,5个connection,5个resultset.还是我的设计上有问题,我的设计就想是
多个线程,同时读数据库,只不过是每个线程读不同的数据块,就像我前面提到过的一样,0-100,100-200这样读的.
的声明就可以看出来.而你在每次方法执行的最后有
try {
conn.close();
conn = null;
} catch (Exception e) {
} connection已经关闭.也就是说resultset也关闭了.是肯定会抛异常的.
import java.sql.*;
import java.util.*;
import org.sky.threadgroup.BeanUtil.*;public class DataHandle { private synchronized Connection getConnection() {
Connection conn = null;
try {
DataConnection dataConn = new DataConnection();
conn = dataConn.getDataConnection();
return conn;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void handle(String start, String end) { Statement stmt = null;
ResultSet rs = null;
StringBuffer sb = new StringBuffer();
/* ArrayList resultList = new ArrayList(); */
DataBean db = null;
Connection conn = null;
try {
conn = getConnection();
if (conn != null) { sb.append("select tid,tname,description,dbvalue,xmlvalue");
sb.append(" from exporttable limit " + start + "," + end);
System.out.println("sql===" + sb.toString());
stmt = conn.createStatement(); rs = stmt.executeQuery(sb.toString());
while (rs.next()) {
db = new DataBean();
db.setTname(StringUtil.replaceNull(rs.getString("tname")));
db.setDescription(StringUtil.replaceNull(rs
.getString("description")));
db.setDbValue(StringUtil.replaceNull(rs
.getString("dbvalue")));
db.setXmlValue(StringUtil.replaceNull(rs
.getString("xmlvalue"))); }
} } catch (Exception e) {
e.printStackTrace();
System.out.println(db.getTname() + ":" + db.getDescription() + ":"
+ db.getDbValue() + ":" + db.getXmlValue());
/* return null; */
} finally {
synchronized (conn) {
try {
if (rs != null) {
rs.close();
rs = null;
}
} catch (Exception e) {
}
try {
if (stmt != null) {
stmt.close();
stmt = null;
}
} catch (Exception e) {
}
try {
if (conn != null) {
conn.close();
conn = null;
}
} catch (Exception e) {
}
}
} }}
一会报这个java.sql.SQLException: The result set is closed.一会报这个
java.sql.SQLException: operation not allowed before rs
每个线程使用一个conntion即可,在业务上需要同步的地方同步一点点即可。
你就没看完我的贴,我是在每个线程里用到一个CONNECTION了,怎么没看清就发贴呀!
Properties props = new Properties();
props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:9099");
Context ctx = new InitialContext(props);
ds = (DataSource) ctx.lookup("MySqlDS");
}catch(Exception e){
ds = null;
e.printStackTrace();
}客户端得到CONNECTION是通过ds.getConnection()这样得到的,是不是由于得到的connection不是ThreadLocal的关系?
而且,也没有必要使用synchronized关键字,
因为,按照楼主的思路,应该是每个线程都负责数据处理的整个过程,
只不过,数据来源被拆分了,而已。我想 , 问题的关键,应该是5个线程使用了同一个连接,使得所产生的rs有关联,关闭一个,其他的就不能够使用。
所以,我给楼主一个参考方案。内容如下:
1.创建DataBean,对应查询数据的每一条记录。
2.创建一个固定大小的线程安全的阻塞队列,用于存放查询的数据。
3.使用一个线程,对数据库进行查询,将查询数据放入队列。
(这个查询,可以使用如下方式,多次查询,每次只查一部分,各部分数据不重复)
4.创建4~5个线程,用于对查询数据的处理。
(从队列里面取出数据,进行处理即可)
原来一个EOD要8小时,经我们这样一改进成了40分钟,你说效率有没有提高?关键在于设计,在于编码,更离谱的是我听到过某些人说RS。NEXT这样的操作就不能做并行,我晕,真不想多说你们这样的人!
CSDN只是提供了一个交流的平台,
如果楼主觉得你的水平远高于我们,下次有问题可以不要到这里提。