5台设备分布式处理30项任务,在30项任务全部处理完成时发送邮件通知,需要在最后一个任务完成时触发邮件发送动作,实现方式:
1、程序中实现,在程序中synchronized变量表示剩余任务数;
2、编写触发器?兼容多数据库比较麻烦;
3、利用数据库在程序中判断,行级锁保证数据准确性;
1)每次更新已完成任务数后查询剩余的任务数,为0时表示任务完成,每个任务需要查询一次;
2)利用update语句执行成功时返回更新记录数,特意让最后一次更新记录数为0(不成功),以下为模拟代码:
/** 处理每个任务,finished为true表示最后一个任务 */
public static int doTask(boolean finished)
{
int result = 0;// 执行update语句更新数据库总记录数
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@192.168.100.2:1521:orcl",
"h2do", "h2do");
if(!finished){
//
// TODO:处理其他数据
// 先提交,减少更新完成任务数的锁定时间
conn.commit();
}
/* 条件finished=total-1时表示最后一个任务,<total-1时才能更新成功,最后一个任务更新失败 */
stmt = conn.prepareStatement(
"update t_progress set finished = finished + 1 where id = ? and finished < total - ?");
stmt.setInt(1, 1);
stmt.setInt(2, finished ? 0 : 1);
result = stmt.executeUpdate();
/*
* 也可在这里select total-finished from t_progress where id = 1
* 根据未完成数判断是否所有任务均已完成
*/
conn.commit();
} catch (SQLException 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 Throwable
{
oracle.jdbc.driver.OracleDriver.class.newInstance();
/*模拟30个任务并发处理*/
for (int i = 0; i < 30; i++)
{
new Thread(new Runnable() {
@Override
public void run() {
int result = doTask(false);
if (0 == result) {
result = doTask(true);
if(1 == result){
System.out.println("发送所有任务完成邮件。。。");
}else{
//TODO:记录日志;
}
}
}
}).start();
}
}
附:
create table t_progress
(
id integer not null,
total integer not null,
finished integer default 0 not null,
constraint pk_t_progress primary key (id)
);
insert into t_progress (ID, TOTAL, FINISHED) values (1, 30, 0);
版权声明:本文为CSDN博主「weixin_34292959」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_34292959/article/details/91594247