public class IdWorker { // worker编号位数 private static final long WORKER_BITS = 6L; // worker编号最大值,决定支持的部署节点数量 private static final long MAX_WORKER_ID = -1L ^ (-1L << WORKER_BITS); // 毫秒内自增位数,每毫秒最大序号支持65535 private static final long SEQUENCE_BITS = 16L; // worker编号偏移量 private static final long WORKER_SHIFT = SEQUENCE_BITS; // 时间偏移量 private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_BITS; // 序号掩码 private static final long SEQUENCE_MASK = -1L ^ (-1L << SEQUENCE_BITS); // 毫秒基线:2015-01-01 00:00:00 private static final long BASE_TIMESTAMP = 1420041600000L; private final long workerId; private volatile long sequence = 0L; private volatile long lastTimestamp = -1L; /** * 从环境变量中获取worker编号,每个部署环境编号不能重复 */ public IdWorker() { this(Misc.parseLong(System.getProperty("app.workerId"), 0L)); } /** * 每个部署环境编号不能重复 * * @param workerId Worker编号 */ public IdWorker(long workerId) { if (workerId > MAX_WORKER_ID || workerId < 0) { throw new IllegalArgumentException(String.format("Worker Id can't be greater than %d or less than 0", MAX_WORKER_ID)); } this.workerId = workerId; } /** * 获取下一个ID * * @return */ public synchronized long next() { long ts = System.currentTimeMillis(); if (lastTimestamp == ts) { sequence = (sequence + 1) & SEQUENCE_MASK; // 当前毫秒的序号已经用完,取下一个毫秒 if (sequence == 0) { ts = nextMillis(lastTimestamp); } } else { sequence = 0L; } if (ts < lastTimestamp) { throw new RuntimeException(String.format( "Clock moved backwards. Refusing to generate id for %d millseconds", lastTimestamp - ts)); } lastTimestamp = ts; return ((ts - BASE_TIMESTAMP) << TIMESTAMP_SHIFT) | (workerId << WORKER_SHIFT) | sequence; } // FIXME:当机器时间被调早时,会导致CPU过高。此处可以考虑进行阻塞 private long nextMillis(final long lastTimestamp) { long ts = System.currentTimeMillis(); while (ts <= lastTimestamp) { ts = System.currentTimeMillis(); } return ts; } }
import java.io.File; import java.security.MessageDigest; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import com.assess.lang.AppException; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; public final class TextUtil { public static final int NO_TRIM = 0; public static final int TRIM_TO_NULL = 1; public static final int TRIM_TO_BLANK = 2; /** * 创建文件目录时使用的质数,默认每个文件夹下使用 */ private static final int SEED = 8999; private static final char[] CHARS_DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .toCharArray(); private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); private TextUtil() { } /** * 将日期(时间)格式化成指定格式的字符串 * * @param date 日期(时间)对象 * @param pattern 格式化模式 * @return */ public static String formatTime(Date date, String pattern) { return new SimpleDateFormat(pattern).format(date); } /** * 将日期(时间)字符串解析成日期时间对象 * * @param val 日期(时间)字符串 * @param pattern 时间模式 * @return 返回日期对象,如果解析失败,则返回null */ public static Date parseTime(String val, String pattern) { try { return new SimpleDateFormat(pattern).parse(val); } catch (ParseException e) { return null; } } /** * 使用单个字符分割字符串 * * @param value * @param delim * @return */ public static String[] split(String value, char delim) { return split(value, delim, TRIM_TO_BLANK); } /** * 使用单个字符分割字符串 * * @param value * @param delim * @param trimFlag Trim方式 * @return */ public static String[] split(String value, char delim, int trimFlag) { final int end = value.length(); final List<String> res = new ArrayList<String>(); int start = 0; for (int i = 0; i < end; i++) { if (value.charAt(i) == delim) { if (start == i) { res.add(""); } else { res.add(value.substring(start, i)); } start = i + 1; } } if (start == 0) { res.add(value); } else if (start != end) { res.add(value.substring(start, end)); } else { for (int i = res.size() - 1; i >= 0; i--) { if (res.get(i).isEmpty()) { res.remove(i); } else { break; } } } String[] ret = res.toArray(new String[res.size()]); if (trimFlag > 0) { for (int i = 0; i < ret.length; ++i) { if (trimFlag == TRIM_TO_NULL) { ret[i] = trimToNull(ret[i]); } else { ret[i] = trimToEmpty(ret[i]); } } } return ret; } /** * 对字符串进行MD5编码后转为16进制字符串 * * @param src * @return */ public static String md5(String src, String salt) { return toHexString(digest("MD5", src, salt)); } /** * 对对象进行MD5编码后转为16进制字符串 * * @param src * @return */ public static String md5(Object obj, String salt) { return toHexString(digest("MD5", toBytes(obj), salt)); } /** * 对字符串进行SHA-256编码后转为16进制字符串 * * @param src * @return */ public static String sha256(String src, String salt) { return toHexString(digest("SHA-256", src, salt)); } /** * 对字符串进行SHA-256编码后转为16进制字符串 * * @param src * @return */ public static byte[] bSha256(String src, String salt) { return digest("SHA-256", src, salt); } /** * 合并两个字节数组 * * @param x * @param y * @return */ public static byte[] merge(byte[] x, byte[] y) { byte[] b = new byte[x.length + y.length]; System.arraycopy(x, 0, b, 0, x.length); System.arraycopy(y, 0, b, x.length, y.length); return b; } /** * 转换字节数组为16进制字串 * * @param b 字节数组 * @return 16进制字串 */ public static String toHexString(byte[] b) { StringBuilder buf = new StringBuilder(b.length * 2); int n = 0; for (int i = 0; i < b.length; i++) { n = b[i]; if (n < 0) { n += 256; } buf.append(HEX_DIGITS[n >> 4]).append(HEX_DIGITS[n % 16]); } return buf.toString(); } /** * 根据给定的key和seed,生成唯一的有效文件路径。 有效文件路径需要满足: 1、每个文件夹下不超过10000个文件; 2、可以根据文件路径和seed还原key * * @param key 用来生成文件路径的一个唯一数值,一般为文件的ID * @param deep 生成文件路径的有效深度,实际生成的路径深度为deep+1 * @return */ public static String dir(long key) { return dir(key, 2, SEED); } /** * 根据给定的key和seed,生成唯一的有效文件路径。 有效文件路径需要满足: 1、每个文件夹下不超过10000个文件; 2、可以根据文件路径和seed还原key * * @param key 用来生成文件路径的一个唯一数值,一般为文件的ID * @param deep 生成文件路径的有效深度,实际生成的路径深度为deep+1 * @return */ public static String dir(long key, int deep) { return dir(key, deep, SEED); } /** * 根据给定的key和seed,生成唯一的有效文件路径。 有效文件路径需要满足: 1、每个文件夹下不超过10000个文件; 2、可以根据文件路径和seed还原key * * @param key 用来生成文件路径的一个唯一数值,一般为文件的ID * @param deep 生成文件路径的有效深度,实际生成的路径深度为deep+1 * @param seed 文件夹最大数量,有效取值为小于10000的质数 * @return */ public static String dir(long key, int deep, long seed) { StringBuilder buf = new StringBuilder(32); for (int i = 0; (i < deep) && (key > 0); i++) { base62(buf, key % seed); buf.append(File.separatorChar); key = key / seed; } return buf.append(key).toString(); } /** * 生成随机的字符串,字符串有效字符为数字和字母 * * @param length 字符串长度 * @return */ public static String salt(int length) { StringBuilder buf = new StringBuilder(length); for (int i = 0; i < length; i++) { buf.append(CHARS_DIGITS[(int) (Math.random() * CHARS_DIGITS.length)]); } return buf.toString(); } public static boolean isBlank(CharSequence cs) { int strLen; if ((cs == null) || ((strLen = cs.length()) == 0)) { return true; } for (int i = 0; i < strLen; i++) { if (Character.isWhitespace(cs.charAt(i)) == false) { return false; } } return true; } public static boolean isBlank(CharSequence cs, int end) { int strLen; if ((cs == null) || ((strLen = cs.length()) == 0)) { return true; } if ((end > 0) && (end < strLen)) { strLen = end; } for (int i = 0; i < strLen; i++) { if (Character.isWhitespace(cs.charAt(i)) == false) { return false; } } return true; } public static boolean isNotBlank(CharSequence cs) { return !isBlank(cs); } public static boolean isEmpty(CharSequence cs) { return (cs == null) || (cs.length() == 0); } public static boolean startsWith(String s, char c) { if (s.length() == 0) { return false; } return s.charAt(0) == c; } public static boolean endsWith(String s, char c) { if (s.length() == 0) { return false; } return s.charAt(s.length() - 1) == c; } public static String trim(String cs) { return cs == null ? null : cs.trim(); } public static String trimToNull(String cs) { String s = trim(cs); return isEmpty(s) ? null : s; } public static String trimToEmpty(String cs) { String s = trim(cs); return s == null ? "" : s; } public static String trimToFlag(String src, String flag) { int index = src.indexOf(flag); if (index == -1) { return src; } return src.substring(0, index); } public static Long toLong(Object o) { if (o instanceof Long) { return (Long) o; } if (o instanceof String) { return Misc.parseLong((String) o, 0L); } if (o instanceof Integer) { return ((Integer) o).longValue(); } return null; } public static Integer toInteger(Object o) { if (o instanceof Long) { return ((Long) o).intValue(); } if (o instanceof String) { return Misc.parseInt((String) o, 0); } if (o instanceof Integer) { return (Integer) o; } return null; } @SuppressWarnings("unchecked") public static List<Long> toLongList(Object o) { if (!(o instanceof List)) { return Collections.EMPTY_LIST; } List<Object> list = (List<Object>) o; List<Long> result = new ArrayList<Long>(list.size()); for (Object e : list) { result.add(toLong(e)); } return result; } @SuppressWarnings("unchecked") public static List<Integer> toIntegerList(Object o) { if (!(o instanceof List)) { return Collections.EMPTY_LIST; } List<Object> list = (List<Object>) o; List<Integer> result = new ArrayList<Integer>(list.size()); for (Object e : list) { result.add(toInteger(e)); } return result; } public static String like(String src) { return like(src, LikeType.ALL); } public static String like(String src, LikeType type) { src = trim(src); if (src == null) { return src; } if (type == LikeType.LEFT) { return "%" + src; } if (type == LikeType.RIGHT) { return src + "%"; } return "%" + src + "%"; } private static void base62(StringBuilder buf, long val) { while (val > 0) { buf.append(CHARS_DIGITS[(int) (val % 62)]); val /= 62; } } private static byte[] digest(String algorithm, String src, String salt) { return digest(algorithm, src.getBytes(), salt); } private static byte[] digest(String algorithm, byte[] bytes, String salt) { try { if ((salt != null) && (salt.length() > 0)) { bytes = merge(bytes, salt.getBytes()); } bytes = MessageDigest.getInstance(algorithm).digest(bytes); } catch (Exception e) { // 忽略异常 } return bytes; } public static byte[] toBytes(Object obj) { try { Output output = new Output(new byte[2048], -1); new Kryo().writeObject(output, obj); output.flush(); return output.toBytes(); } catch (Exception e) { throw new AppException("Serialize Object failed", e); } } public static <T> T readBytes(byte[] bytes, Class<T> clazz) { if (bytes == null) { return null; } try { return new Kryo().readObject(new Input(bytes, 0, bytes.length), clazz); } catch (Exception e) { return null; } } public static byte[] int2Bytes(int num) { byte[] byteNum = new byte[4]; for (int ix = 0; ix < 4; ++ix) { int offset = 32 - (ix + 1) * 8; byteNum[ix] = (byte) ((num >> offset) & 0xff); } return byteNum; } public static int bytes2Int(byte[] byteNum) { int num = 0; for (int ix = 0; ix < 4; ++ix) { num <<= 8; num |= (byteNum[ix] & 0xff); } return num; } public static byte[] long2Bytes(long num) { byte[] byteNum = new byte[8]; for (int ix = 0; ix < 8; ++ix) { int offset = 64 - (ix + 1) * 8; byteNum[ix] = (byte) ((num >> offset) & 0xff); } return byteNum; } public static long bytes2Long(byte[] byteNum) { long num = 0; for (int ix = 0; ix < 8; ++ix) { num <<= 8; num |= (byteNum[ix] & 0xff); } return num; } public static enum LikeType { LEFT, RIGHT, ALL } }
public final class Misc { private Misc() { } /** * 判断集合是否为null或空 * * @param c * @return */ public static boolean isEmpty(Collection<?> c) { return ((c == null) || (c.size() == 0)); } /** * 将字符串按','分割后存入Set * * @param s * @return */ public static Set<String> asSet(String s) { if ((s == null) || (s.trim().length() == 0)) { return null; } String[] parts = TextUtil.split(s, ','); Set<String> set = new HashSet<String>(parts.length); for (String part : parts) { String trimmed = part.trim(); if (trimmed.length() > 0) { set.add(trimmed); } } return set; } /** * 生成上传文件的临时保存路径,并使用UUID对上传文件重命名。 * * @param dir 临时文件保存的目录。使用系统绝对路径,一般使用" * @param suffix 文件名后缀 * @param max 最大重试次数 * @return 创建成功时返回文件的绝对路径,创建失败时返回null */ public static File randomFile(String dir, String suffix, int max, boolean create) throws IOException { File p = new File(dir, TextUtil.formatTime(new Date(), "yyyyMMdd")); if (p.exists() || p.mkdirs()) { for (int i = 0; i < max; ++i) { File f = new File(p, TextUtil.salt(8) + suffix); if (!f.exists()) { if (create && f.createNewFile()) { return f; } } } } return null; } /** * 安全地将字符串解析成整型 * * @param s 字符串 * @param defaultValue 字符串为空(包括null)或解析失败时返回默认值 * @return */ public static int parseInt(String s, int defaultValue) { if ((s != null) && (s.length() > 0)) { try { return Integer.parseInt(s); } catch (NumberFormatException e) { // 忽略异常 } } return defaultValue; } /** * 安全地将字符串解析成长整型 * * @param s 字符串 * @param defaultValue 字符串为空(包括null)或解析失败时返回默认值 * @return */ public static long parseLong(String s, long defaultValue) { if ((s != null) && (s.length() > 0)) { try { return Long.parseLong(s); } catch (NumberFormatException e) { // 忽略异常 } } return defaultValue; } /** * 获取远程客户端的IP地址 * * @param request * @return 没有找到ip时返回null */ public static String parseIp(HttpServletRequest request) { String ip = request.getHeader("X-Real-IP"); if (TextUtil.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) { return ip; } ip = request.getHeader("X-Forwarded-For"); if (!TextUtil.isBlank(ip)) { for (String value : TextUtil.split(ip, ',', TextUtil.TRIM_TO_NULL)) { if (value != null) { if ("unknown".equalsIgnoreCase(ip)) { break; } return value; } } } return request.getRemoteAddr(); } }
相关推荐
### C#根据时间产生ID编号 在软件开发中,经常需要为每一笔数据或记录生成唯一的标识符(ID)。在某些场景下,基于时间戳来生成ID是一种常见且有效的方法。这种方式不仅简单易行,还能确保大部分情况下ID的唯一性。...
大批量插入数据时,高并发时,可避免id的重复且速度快
在本文中,我们将深入探讨如何利用T1定时器来产生ID读卡头所需的125kHz载波PWM信号,并且重点讨论占空比的可调性。 首先,初始化T1定时器是生成PWM的关键步骤。在`PWM_Init`函数中,我们看到P0.7引脚被配置为输出,...
证状: 部分LeadBBS数据库,产生数据库错误,导致主键丢失(字段名ID),并产生ID号相同的重复数据. 作用: 此程序即用来删除ID号相同的重复帖子数据. 副作用...
* * Twitter_Snowflake ... * * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
分布式ID生成,雪花算法生成唯一ID工具类。...整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右
n 功能 4:产生ID n 功能分析:根据角色产生相应的ID n 功能 5:出版社序号 n 功能分析:根据序号分配对应的出版社 n 功能 6:出版社年份序号 n 功能分析:根据序号分配对应的出版年份 n 功能 7:借书 n 功能...
3. 玩家程序连接游戏服务器,产生 ID2。 4. 游戏服务器和登陆服务器联系,ID2 和 ID1 互相认识。 为了保证信息安全,我们需要加密传送的信息。可以采用 DES 方式对信息进行加密和解密,而 DES 的密钥可以通过 RSA ...
如果ID字段已有值,则触发器会确保序列值至少等于这个值,以避免未来插入的数据产生ID冲突。 这种结合使用序列和触发器的方法是Oracle中一种常见的主键自增实现方式。它不仅确保了主键的唯一性和连续性,还大大提高...
最近做了一个类似用js实现思维导图的功能,作为思维导图,一定会有树状结构的数据产生,在操作里面的节点时会经常需要查找节点 的父节点及父节点。 对于未知层级的树状数据,用for循环是无法实现的,因为不知道要...
此外,修改后的ID可能会与软件许可证产生冲突,甚至引发系统不稳定。 总的来说,HookdiskID是一个强大的工具,能够帮助用户解决特定场景下的硬盘ID问题,但同时也需要谨慎使用,以避免不必要的麻烦。在实际应用中,...
例如,一些应用可能因为识别到IMEI变化而拒绝服务,或者在你试图恢复备份时产生冲突。此外,某些运营商和手机制造商可能会对IMEI的更改有严格的限制,甚至可能会封锁非法修改IMEI的设备。因此,除非有充分的理由,...
ID卡读取的过程中,读卡器发出特定频率的电磁波,当ID卡进入这个场强范围内时,其内部的线圈会感应到电磁波并产生电流,驱动芯片工作。芯片接收到信号后,将卡上的数据编码并通过反向电磁场回传给读卡器。读卡器接收...
ID ID(Hex) Name ID ID(Hex) Name ID ID(Hex) Name 1 0001 US7ASCII 2 0002 WE8DEC 3 0003 WE8HP 4 0004 US8PC437 5 0005 WE8EBCDIC37 6 0006 WE8EBCDIC500 7 0007 WE8EBCDIC1140 8 0008 WE8EBCDIC285 9 0009
- **N沟道耗尽型MOSFET**:即使在uGS=0时,由于预先存在的反型层,已经存在沟道,施加uDS即可产生iD。栅源电压uGS的改变会调整沟道宽度,从而影响iD。 - **P沟道MOSFET**:其工作原理与N沟道MOSFET类似,但导电...
在深入探讨"Acct-Session-id"这一概念之前,我们首先需要理解其在IT网络管理与计费系统中的核心作用。"Acct-Session-id",即会计会话标识符,是RADIUS(Remote Authentication Dial In User Service)协议中一个关键...
使用雪花算法生成全局唯一订单编号,确保在高并发场景下不会产生ID碰撞。 2. 分布式锁 通过Redis、Redisson和Zookeeper实现分布式锁,解决高并发场景下的数据一致性问题。 3. 消息队列 使用RabbitMQ实现消息的...
Originator ID由RR产生,使用的Router ID的值标识路由的始发者,用于防止集群内产生路由环路。 当一条路由第一次被RR反射的时候,RR将Originator ID属性加入这条路由,标识这条路由的发起路由器。如果一条路由中已经...
idinput 函数的基本语法为:`u = idinput(N,type,band,levels)`,其中 `N` 表示产生的序列的长度,`type` 指定产生信号的类型,`band` 指定信号的频率成分,`levels` 指定输入的水平。 对于不同类型的信号,idinput ...
在上述代码中,`generateId`方法是线程安全的,因为使用了`synchronized`关键字,防止多线程并发访问时产生的数据不一致问题。`ThreadLocalRandom`被用来在每个线程内部生成随机数,它比`Random`更快且更适合多线程...