多进程多线程,全局唯一的id自增
public class IdGenerator { private final static String SELECT_ALL_ID_INFO = "SELECT Name FROM IDGenInfo"; private final static String SELECT_ID_INFO = "SELECT Current, Step FROM IDGenInfo WHERE Name = ? FOR UPDATE"; private final static String UPDATE_ID_INFO = "UPDATE IDGenInfo SET Current = Current + Step WHERE Name = ?"; private ConcurrentHashMap<String, IdInfo> counters = new ConcurrentHashMap<String, IdInfo>(); private boolean enabled = true; private IdGenerator() { ArrayList<String> names = DbManager.instance().executeQuery_ObjectList( SELECT_ALL_ID_INFO, ScalarResultBuilder.stringResultBuilder); for (String name : names) { counters.put(name, new IdInfo(name, 0, 0)); } } private final static IdGenerator _instance = new IdGenerator(); public static IdGenerator instance() { return _instance; } private long genNewId(String name) { if (!enabled){ ApplicationLocal.instance().error("invalid operation:can Not gen new id after persist!"); return -1; } IdInfo ii = counters.get(name); if (ii == null) { return -1; } synchronized (ii) { if (ii.count == 0) { fillIdInfo(ii, name); if (ii.count == 0) { return -1; } } ii.count--; ii.val++; return ii.val; } } public int next(String name) { return (int)genNewId(name); } public long nextBigId(String name){ return genNewId(name); } private void fillIdInfo(IdInfo ii, String name) { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = DbManager.instance().getConnection(); conn.setAutoCommit(false); stmt = conn.prepareStatement(SELECT_ID_INFO); stmt.setString(1, name); rs = stmt.executeQuery(); rs.next(); ii.val = rs.getLong("Current"); ii.count = rs.getInt("Step"); stmt.close(); stmt = conn.prepareStatement(UPDATE_ID_INFO); stmt.setString(1, name); stmt.execute(); conn.commit(); } catch (Exception ex) { try { conn.rollback(); } catch (Exception e) { } ii.reset(); ApplicationLocal.instance().error("fill id info error :", ex); } finally { DbManager.releaseDbResource(rs, stmt, conn); } } static class IdInfo { public String name; public long val; public int count; public IdInfo(String name, long val, int count) { this.name = name; this.val = val; this.count = count; } public void reset() { this.val = -1; this.count = 0; } } }
表结构:
CREATE TABLE `IDGenInfo` (
`Name` VARCHAR(45) NOT NULL,
`Current` BIGINT(10) UNSIGNED NOT NULL,
`Step` MEDIUMINT(8) UNSIGNED NOT NULL,
PRIMARY KEY (`Name`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;