雪花算法:
public class SnowflakeIdGenerator {
private final long epoch = 1626804000000L; // 定义起始时间戳,这里设置为2021-07-21 00:00:00 UTC
private final long workerIdBits = 5L; // 机器ID所占的位数
private final long sequenceBits = 10L; // 序列号所占的位数
private final long maxWorkerId = -1L ^ (-1L << workerIdBits); // 最大的机器ID,用于做位运算
private final long sequenceMask = -1L ^ (-1L << sequenceBits); // 序列号的掩码,用于取低位
private long workerId; // 机器ID
private long sequence = 0L; // 序列号
private long lastTimestamp = -1L; // 上次生成ID的时间戳
/**
* 构造函数
* @param workerId 机器ID
*/
public SnowflakeIdGenerator(long workerId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("Worker ID must be between 0 and %d", maxWorkerId));
}
this.workerId = workerId;
}
/**
* 生成下一个唯一ID
* @return long 类型的唯一ID
*/
public synchronized long nextId() {
long timestamp = System.currentTimeMillis(); // 获取当前时间戳
// 如果当前时间小于上次ID生成的时间戳,则说明系统时钟回退过,抛出异常
if (timestamp < lastTimestamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}
// 如果是同一时间生成的,则进行序列号累加
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask; // sequence自增,并通过sequenceMask防止溢出
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp); // 如果sequence溢出,则阻塞到下一个毫秒,获取新的时间戳
}
} else {
sequence = 0L; // 如果是新的时间戳,则将序列号置为0
}
lastTimestamp = timestamp; // 更新上次生成ID的时间戳
// 使用位运算生成最终的ID,并返回
return ((timestamp - epoch) << (workerIdBits + sequenceBits))
| (workerId << sequenceBits)
| sequence;
}
/**
* 阻塞到下一个毫秒,直到获得新的时间戳
* @param lastTimestamp 上次生成ID的时间戳
* @return 当前时间戳
*/
private long tilNextMillis(long lastTimestamp) {
long timestamp = System.currentTimeMillis();
while (timestamp <= lastTimestamp) {
timestamp = System.currentTimeMillis();
}
return timestamp;
}
/**
* 主函数,用于测试生成ID
* @param args 参数
*/
public static void main(String[] args) {
SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1); // 设置机器ID
for (int i = 0; i < 10; i++) {
long id = idGenerator.nextId(); // 生成新的ID
System.out.println("Generated Id: " + id); // 打印生成的ID
}
}
}
拉取在线用户的思路:登录过后开启线程这就是在线用户,将其线程放入集合中管理,key为ID,遍历集合则可以获取到所有的在线用户
获取在线用户的部分代码:
// 集合遍历,遍历hashmap的key
Iterator<String> iterator = hm.keySet().iterator();
String onlineUserList = "";
while (iterator.hasNext()) {
onlineUserList += iterator.next() + " ";
}
return onlineUserList;
Iterator<String> iterator = hm.keySet().iterator();
:这行代码通过hm.keySet().iterator()
获取了HashMaphm
的所有键的迭代器(iterator)。hm.keySet()
返回HashMap中所有键的集合,然后iterator()
方法返回这个集合的迭代器,用于逐个访问集合中的元素。String onlineUserList = "";
:这行代码定义了一个空字符串onlineUserList
,用来存储遍历得到的所有键。while (iterator.hasNext()) {
:这是一个 while 循环,它的条件是iterator.hasNext()
,即迭代器中是否还有下一个元素。如果有,进入循环体。onlineUserList += iterator.next() + " ";
:在循环体内部,iterator.next()
方法返回迭代器的下一个键,并将其添加到onlineUserList
字符串后面,同时在每个键之间添加一个空格。return onlineUserList;
:最后,当迭代器遍历完所有键后,退出循环,并返回拼接好的onlineUserList
字符串,其中包含了HashMap中所有键的列表。
查找数据库某个字段的所有数据:
try {
// 加载并注册JDBC驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// Class.forName("com.mysql.jdbc.Driver");
// 建立数据库连接
conn = DriverManager.getConnection(URL, USER, PASSWORD);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
}
//遍历数据库
// 创建Statement对象
//这个也是个接口,用于执行不带参的,PreparedStatement pstmt是其子接口,执行带参的语句
Statement stmt = null;
try {
stmt = conn.createStatement();
} catch (SQLException e) {
throw new RuntimeException(e);
}
try {
// 执行查询
String sql = "SELECT userId FROM account";
ResultSet rs = stmt.executeQuery(sql);
String onlineUserList="";
// 处理查询结果
while (rs.next()) {
// 假设userId是整型,根据实际情况调整
String userId = rs.getString("userId");
onlineUserList+=userId+" ";
}
return onlineUserList;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
try {
if(rs!=null){
rs.close();
}
if(stmt!=null){
stmt.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}