我在这里有一个相当简单的Java类,它创建了2个线程池......
连接到正在运行的URL流并逐行读入条目,将每个条目提交到后端MySQL数据库。
产生几个线程,每个线程将执行相同的过程(如下)
1.从上面获取最旧的DB条目
2.Parse并相应地处理
3.将几个部分保存到另一个数据库表
4.从运行表中删除此DB条目以表示分析已完成
5.End Thread
我需要2个池的原因是因为读取过程比分析快得多,如果我阅读&分析每个条目,因为它通过条目备份太快而传入的流中断。通过实现这种分离,读取可以在需要的时候尽快发生,并且分析可以尽可能快地进行,因为它可以知道要赶上的记录是安全的并且可以跟上。
我遇到的问题是每个并发线程都获得了相同的最旧记录。我需要知道最好的方法是确保单独的线程全部并发运行,但每个线程都访问唯一最旧的DB条目。
提前致谢。
EDIT =================================
感谢大家到目前为止的回复......
为了进一步扩展我在此尝试的当前设置,这个代码段可能会有用......
try
{
String strQuery1 = "SELECT lineID,line FROM lineProcessing ORDER BY lineID ASC LIMIT 1;";
String strQuery2 = "DELETE from lineProcessing WHERE lineID = ?";
DBConnector dbc = new DBConnector(driver,url,userName,passwd);
Connection con = dbc.getConnection();
con.setAutoCommit(false);
PreparedStatement pstmt = con.prepareStatement(strQuery1);
rs = pstmt.executeQuery();
//Now extract the line & Id from the returned result set
while (rs.next()) {
lineID = Integer.parseInt(rs.getString(1));
line = rs.getString(2);
} //end while
//Now delete that entry so that it cannot be analysed again...
pstmt = con.prepareStatement(strQuery2);
pstmt.setString(1, lineID.toString());
int res=pstmt.executeUpdate();
con.commit();
con.setAutoCommit(true);
con.close();
}
catch (SQLException e) {
System.out.println(">>>EXCEPTION FOUND IN QUERY = " + strQuery1 + " __or__ " + strQuery2);
e.printStackTrace();
}
...因此,您可以看到基本上打开数据库连接,将其设置为“Autocommit = false”,执行QUERY1,执行QUERY2,提交两个事务,最后关闭连接。这应该是每个单独的线程都需要完成的。问题是我在分析线程池中运行的每个X线程都被生成并且所有这些代码同时执行(这是我期望的)但是不尊重对DB的单连接访问我认为我已经设置以上。然后他们都返回同一条线进行分析。当线程接下来循环进行迭代#2时,它们都会返回这个新的最后一行,以便在上一次删除之后进行分析。
请进一步提出建议 - 包括通过java强制执行事务SQL的一个很好的例子吗?
再次感谢大家。
答案 0 :(得分:1)
首先,添加一个可为空的datetime列,表示该行已在某个时间“被拾取”。
然后在你的处理线程中:
确保您的isolation level设置为至少READ UNCOMMITTED
,并且没有两个线程应该获得相同的行。此外,如果处理线程死亡并放弃它的行,您可以通过定期查询“拾取”时间早于某个值的行来找到它,并通过将拾取时间设置为空来重新处理这些行。
或者只是切换到事务性消息队列,它会自动为您完成大部分操作。
答案 1 :(得分:0)
另一个解决方案是让工作线程等待包含该行键的单例。写入行,将键放在对象中,然后通知。 “下一个”工作线程将获取密钥并对其进行操作。你需要确保一个工人在等待什么不是。