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);
时间: 2024-10-02 14:40:35