有一个任务表,每个任务有n个事项要并发处理,
每个事项完成时需要更新已完成数,即finished+1,当n个事项全部处理完成即整个任务完成时需要做任务的统计工作。
数据库通过行级锁来保证并发更新准确性,测试代码如下:
public class Concurrency {
/**执行更新语句,根据commitImmediately决定是否立即提交*/
public static int executeUpdate(String sql, boolean commitImmediately)
{
Connection conn = null; Statement stmt = null; int result = 0;
try
{
conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "h2do", "h2do");
conn.setAutoCommit(false);
stmt = conn.createStatement();
result = stmt.executeUpdate(sql);
if(!commitImmediately)
{
System.out.println("挂起等待输入字符模拟提交前其他操作...");
System.in.read();
}
conn.commit();
}catch(Exception e){
e.printStackTrace();
}finally{
try{if(null != stmt)stmt.close();}catch(Exception e){}
try{if(null != conn)conn.close();}catch(Exception e){}
}
return result;
}
public static void main(String[] args) throws Exception{
oracle.jdbc.driver.OracleDriver.class.newInstance();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
//1、更新任务1的记录,挂起等待命令行输入字符才提交
executeUpdate("update task set finished = finished + 1 where id = 1", false);
System.out.println("step 1 finished.");
}
});
t1.start();
t1.join(1000);//保证线程进入执行状态
new Thread(new Runnable(){
@Override
public void run() {
//2、更新任务1的记录,并想立即提交,因为有其他线程更新后未提交,记录被锁定需等待锁释放后才能更新
executeUpdate("update task set finished = finished + 1 where id = 1", true);
System.out.println("step 2 finished.");
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
//3、更新同一个表任务2的记录,不受任务1的记录更新影响(尽管id=1的记录已被锁定)
executeUpdate("update task set finished = finished + 1 where id = 2", true);
System.out.println("step 3 finished.");
}
}).start();
}
}
执行结果如下:
挂起等待输入字符模拟其他处理...
step 3 finished.
step 1 finished.
step 2 finished.