我有一个项目,我从文件中读取数据,在数据库中执行一些SQL,并将数据写入数据库。其中一个文件输入字段有25-50个不同的参数(产品属性的值),我必须在将数据写入文件之前进行查询。这是我的过程中最慢的部分 - 所以我认为尝试使用多个线程来实现它是一件好事。
我需要为每个属性值运行一个select语句,如果该值尚不存在,则创建一个新值。创建涉及简单地将SQL和插入语句写入批处理 - 在处理给定产品的所有数据之后,批处理将作为数据库事务的一部分提交。
我有一个AttributeLoader
类来处理所有产品属性 - 包括解析传入的属性信息,查找属性的ID然后查找值的id - 并创建一个新的属性值和id如果没有存在。
我还有一个FindAttrValByIdentifier
类,它是可运行的类,用于检索属性值(如果它已经存在)。我的计划是利用ExecutorService
运行大约20个执行select
查询的线程 - 每个线程将传递一个数据库连接以用于查询数据库。当我运行它 - 它似乎处理一个传入线然后挂起。所以,在某个地方,我似乎有一些东西挂在等待状态。下面是我的代码的框架。有谁看到我出轨的地方?它可能是多个地方,因为我不是Java Guru - 特别是涉及到多个线程时。我试图将代码缩减到适用的行 - 所以如果我剪得太多,请告诉我。
//my control class (SpeedLoader)opens the connection pool
public class SpeedLoader {
private static void initializeConnectionPool() throws PropertyVetoException {
cpds = new ComboPooledDataSource();
cpds.setDriverClass( DB_DRIVER ); //loads the jdbc driver
cpds.setJdbcUrl( DB_CONNECTION );
cpds.setUser(DB_USER);
cpds.setPassword(DB_PASSWORD);
// the settings below are optional -- c3p0 can work with defaults
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(25);
cpds.setMaxStatements(25);
}
public static synchronized Connection getConnection() throws SQLException {
return cpds.getConnection();
}
class AttributeLoader { //this class loads attribute data - and is a single instance that is used throughout the complete load process
AttributeLoader(Connection conn, String filePath, String fileTimestamp) throws Exception {
dbConnection = conn;
initialize(filePath, fileTimestamp);
}
public static void processAttributesForPN(String productPN, long productId) throws Exception{
List<Future<Long>> future=new ArrayList<Future<Long>>();
List<FindAttrValIdByIdentifier> callList = new ArrayList<FindAttrValIdByIdentifier>();
for(Map.Entry<Key, Long> entry : attrValIdCache.entrySet()){ // get values for existing keys
FindAttrValIdByIdentifier getValId = new FindAttrValIdByIdentifier(entry.getKey().attrId, entry.getKey().identifier);
callList.add(getValId);
}
future=executor.invokeAll(callList);
// process results
}
private static void initialize(String filePath, String fileTimestamp) throws Exception {
try {
attributeDataFileReader = new FileReader(filePath+"/"+fileTimestamp+".CatentryAttribute.csv");
attributeBufferedReader = new BufferedReader(attributeDataFileReader);
//other stuff
executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(20);
public static void close() throws IOException, SQLException{// close is not called until all file processing completes
// other stuff
FindAttrValIdByIdentifier.close();
executor.shutdown();
while (!executor.isTerminated()) {
}
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.Callable;
public class FindAttrValIdByIdentifier implements Callable<Long> {
long attrId;
String identifier;
static Connection pooledConnection;
static PreparedStatement psSelectAttrValId;
public FindAttrValIdByIdentifier(long i, String s) throws SQLException {
super();
attrId = i;
identifier = s;
pooledConnection = SpeedLoader.getConnection();
psSelectAttrValId = pooledConnection.prepareStatement("SELECT ATTRVAL_ID FROM ATTRVAL WHERE ATTR_ID=? AND IDENTIFIER=? FOR READ ONLY");
}
public static void close() throws SQLException{
try {pooledConnection.close();} catch (SQLException e) {e.printStackTrace();}
try {psSelectAttrValId.close();} catch (SQLException e) {e.printStackTrace();}
}
public Long call() {
try {
psSelectAttrValId.setLong(1, attrId);
psSelectAttrValId.setString(2, identifier);
ResultSet rs = psSelectAttrValId.executeQuery();
if (rs.next()){
return(rs.getLong(1));
}
// System.out.println("Thread " + m_myId + " is finished. ");
return 0L;
} catch (Exception e) {
System.out.println("Thread got Exception: AtrrId, Identifier= "+attrId+","+identifier+" Error: " + e);
e.printStackTrace();
throw(new Error("AttrId:"+attrId+ " AttrValIdentifier: "+identifier+ " FindAttrValIdByIdentifier.call() "+e.getMessage()));
} finally {
}