import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* 雪花算法的工具类: 雪花算法一共分为五个部分
*
* <p>第一部分:是1bit,就是一个0,没有任何意义。
*
* <p>第二部分:是41bit的时间戳。
*
* <p>第三部分:是5bit,机房id。
*
* <p>第四部分:是5bit,机器id。
*
* <p>第五部分:是12bit,表示序列号 就是这个机房这个机器上,这一毫秒,同时产生的雪花算法的值的序列号。
*
* <p>这说明雪花算法单机一毫秒并发2048.
*/
@Component
public class SnowFlakeUtil {
/** 机器id */
@Value("${snowflake.worker:0}")
private long workerId;
/** 机房id */
@Value("${snowflake.dataCenterId:0}")
private long dataCenterId;
/** 序号 */
private long sequence;
/**
* 雪花算法时间的起点 它其实就是当初算法创立者创立此算法的那个时间点。
*
* <p>因为时间戳只有41位,因此当此算法运行69年左右的时候,时间就会重复。
*
* <p>twepoch可以以现在的时间为值
*
* <p>软件开发,设计的程序,需要保证多长时间不出问题呢?20年。
*/
private long twepoch = 1627462055200L;
/**
* 机房id与机器id都是5位
*
* <p>bit=位
*
* <p>byte=字节=8位=8bit
*/
private long workerIdBits = 5L;
private long dataCenteridBits = 5L;
/**
* 求n为二进制的最大值,怎么求? 2^n 1<<n - 1
*
* <p>最好求数据不需要更多bit。
*
* <p>-1^(-1<<n) => n个1
*
* <p>原码:1000 0001 反码:1111 1110 补码:1111 1111
*
* <p>左移3位:1111 1000 ^ 1111 1111 --------------- 0000 0111
*/
/** 机器号的最大值 */
private long maxWorkId = -1L ^ (-1L << workerIdBits);
/** 机房id的最大值 */
private long maxDataCenterId = -1L ^ (-1L << dataCenteridBits);
/** 序列号的长度 */
private long sequenceBits = 12L;
/** 序列号的最大值 */
private long maxSequence = -1L ^ (-1L << sequenceBits);
/** 机器id左移12位数 */
private long workerIdShift = sequenceBits;
/** 机房id左移17位数 */
private long dataCenterIdShift = sequenceBits + workerIdBits;
/** 时间戳左移22位数 */
private long timestampShift = sequenceBits + workerIdBits + dataCenteridBits;
/** 总体的记录的时间 */
private long lastTimestamp = -1L;
/** 获取时间的方法 */
private long time() {
return System.currentTimeMillis();
}
/** 获取一个新的时间 */
private long nextTime(long lastTimestamp) {
long timestamp = time();
while (timestamp <= lastTimestamp) {
timestamp = time();
}
return timestamp;
}
/** 生成与拼装雪花算法 */
public synchronized long nextId() {
// 获取当前时间
long timestamp = time();
// 和上一次时间比较
if (timestamp < lastTimestamp) {
return -1;
}
// 1毫秒内的并发
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & maxSequence;
if (sequence == 0) {
// 获取一个新的时间,因为这一毫秒sequence已经最大了
timestamp = nextTime(lastTimestamp);
}
} else {
sequence = 0;
}
// 记录这一次生成雪花算法id的时间
lastTimestamp = timestamp;
// 拼装雪花算法的id
return ((timestamp - twepoch) << timestampShift)
| (dataCenterId << dataCenteridBits)
| (workerId << workerIdBits)
| (sequence);
}
}
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/** 异步请求的工具类 */
public class AsyncBatchCallUtil {
/** 对外界提供方法 */
public static void execute(Runnable task) {
executorService.execute(task);
}
/** 线程池服务 */
private static ExecutorService executorService;
static {
// 核心线程数
int corePoolSize = 5;
// 最大线程数
int maxPoolSize = 10;
// 时间
long keepAliveTime = 10;
// 时间单位
TimeUnit unit = TimeUnit.SECONDS;
// 队列
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue(6);
// 默认工厂
ThreadFactory threadFactory = new UserThreadFactory("qianfeng");
// 拒绝策略
RejectedExecutionHandler handler = new MyRejectPolicy();
// 实例化线程池
executorService =
new ThreadPoolExecutor(
corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
}
/** 拒绝策略 */
static class MyRejectPolicy implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(AsyncBatchCallUtil.class.getName() + "的线程队列已经满了");
}
}
/** 线程工厂 */
static class UserThreadFactory implements ThreadFactory {
private final String namePrefix;
private final AtomicInteger nextId = new AtomicInteger(1);
UserThreadFactory(String groupName) {
namePrefix = "From " + UserThreadFactory.class.getName() + "-" + groupName + "-";
}
@Override
public Thread newThread(Runnable r) {
String name = namePrefix + nextId.getAndIncrement();
Thread thread = new Thread(null, r, name);
return thread;
}
}
}
// 使用封装好的线程池执行我们的异步逻辑
AsyncBatchCallUtil.execute(
() -> {
//gifService.createGif(targetFile, fileName, url);
});
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/** 同步调用的工具类 内部要封装线程池与CountDownLatch */
public class SyncBatchCallUtil {
/** 线程池 */
private static ExecutorService executorService;
static {
// 核心线程数
int corePoolSize = 5;
// 最大线程数
int maxPoolSize = 10;
// 时间
long keepAliveTime = 10;
// 时间单位
TimeUnit unit = TimeUnit.SECONDS;
// 队列
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue(6);
// 默认工厂
ThreadFactory threadFactory = new UserThreadFactory("qianfeng-countdownlatch");
// 拒绝策略
RejectedExecutionHandler handler = new MyRejectPolicy();
// 实例化线程池
executorService =
new ThreadPoolExecutor(
corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
}
/** 拒绝策略 */
static class MyRejectPolicy implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(AsyncBatchCallUtil.class.getName() + "的线程队列已经满了");
}
}
/** 线程工厂 */
static class UserThreadFactory implements ThreadFactory {
private final String namePrefix;
private final AtomicInteger nextId = new AtomicInteger(1);
UserThreadFactory(String groupName) {
namePrefix =
"From " + AsyncBatchCallUtil.UserThreadFactory.class.getName() + "-" + groupName + "-";
}
@Override
public Thread newThread(Runnable r) {
String name = namePrefix + nextId.getAndIncrement();
Thread thread = new Thread(null, r, name);
return thread;
}
}
/** 自定义任务类 */
public abstract static class Task implements Runnable {
/** 任务调度的方法 */
public abstract void exe();
/** 内部封装CountDownLatch */
private CountDownLatch countDownLatch;
public void setCountDownLatch(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
// 先执行任务0
try {
exe();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 再让计数器-1
countDownLatch.countDown();
}
}
}
/** 创建一组任务 */
private static boolean createTasks(Task[] tasks) {
// 给这组任务实例一个CountDownLatch
// 注意:是一组任务对应一个CountDownLatch
// 有多少个任务,计数器就是多少,所以构造方法参数为tasks.length
CountDownLatch countDownLatch = new CountDownLatch(tasks.length);
// 给每一个任务设定相同的CountDownLatch
for (int i = 0; i < tasks.length; i++) {
tasks[i].setCountDownLatch(countDownLatch);
}
// 每一个task类型其实都是Runnable类型,它应该用线程池来执行。
for (int i = 0; i < tasks.length; i++) {
// 启动每一个任务
executorService.execute(tasks[i]);
}
// 卡住当前线程
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 给外界提供可调用的方法
*
* @param tasks 指定一组任务
* @return 这组任务是否创建成功
*/
public static boolean batch(Task... tasks) {
return createTasks(tasks);
}
}
/** 测试同步调用聚合接口的工具类 */
public class TestSyncBatchUtil {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
SyncBatchCallUtil.batch(
new Task() {
@Override
public void exe() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// userClient.search("userId");
}
},
new Task() {
@Override
public void exe() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},
new Task() {
@Override
public void exe() {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println("任务总耗时为:" + (System.currentTimeMillis() - startTime) + "毫秒。");
}
}
import java.lang.ref.SoftReference;
/**
* 内存缓存组件 LRU算法
*
* <p>1、使用LRU算法进行内存淘汰。
*
* <p>2、使用软引用,来避免因为LRU算法导致原本的SSM模型内存不够用。
*/
public class CacheUtil {
/** 链表的头 */
private Node top;
/** 链表的尾 */
private Node bottom;
/** 缓存区的大小(缓存对象的个数) */
private Integer size;
/** 当前元素个数 */
private int length;
public CacheUtil(int size) {
this.size = size;
}
public Object get(String key) {
synchronized (size) {
// 1-->2-->3
// 删除,头插。
if (length == 0) {
return null;
} else {
// 链表版的for循环标准形式
for (Node p = top; p != null; p = p.next) {
if (p.key.equals(key)) {
// 找到了
if (p == top) {
Object object = p.value.get();
if (object == null) {
// 软引用的对象被回收了
top = top.next;
length--;
return null;
} else {
return object;
}
}
// 找到的元素并不是头结点
if (p.next != null) {
// 找到的这个元素不是头也不是尾
p.next.prev = p.prev;
p.prev.next = p.next;
Object object = p.value.get();
if (object == null) {
length--;
return null;
} else {
p.next = top;
top.prev = p;
top = p;
p.prev = null;
return object;
}
} else {
// 找到的元素是链表的尾部
bottom = bottom.prev;
bottom.next = null;
Object object = p.value.get();
if (object == null) {
length--;
return null;
} else {
p.next = top;
top.prev = p;
top = p;
p.prev = null;
return object;
}
}
}
}
}
}
return null;
}
public void put(String key, Object value) {
synchronized (size) {
if (length > 0) {
// 先查就可以了
for (Node p = top; p.next != null; p = p.next) {
if (key.equals(p.key)) {
// 找到了
// 把p删了
if (p == top) {
top = top.next;
} else if (p == bottom) {
bottom = bottom.prev;
} else {
p.next.prev = p.prev;
p.prev.next = p.next;
}
length--;
}
}
}
// 实例了一个软引用
SoftReference<Object> softReference = new SoftReference<Object>(value);
// 头插尾删
if (length == 0) {
top = new Node();
bottom = top;
top.key = key;
top.value = softReference;
length++;
return;
} else if (length <= size) {
// 头插
Node temp = new Node();
temp.next = top;
top.prev = temp;
temp.key = key;
temp.value = softReference;
top = temp;
if (length < size) {
length++;
}
}
if (length >= size) {
// 尾删
bottom = bottom.prev;
bottom.next = null;
}
}
}
/** 双向链表实现 定义双向链表 */
private class Node {
String key;
SoftReference<Object> value;
Node prev;
Node next;
}
}
/** 测试 */
public static void main(String[] args) {
CacheUtil cacheUtil = new CacheUtil(5);
for (int i = 1; i <= 5; i++) {
cacheUtil.put("a" + i, "" + i);
}
System.out.println(cacheUtil.get("a2"));
// 下面代码执行,出去的是谁?
cacheUtil.put("a6", "6");
System.out.println(cacheUtil.get("a1"));
cacheUtil.put("a7", "7");
System.out.println(cacheUtil.get("a3"));
System.out.println(cacheUtil.get("a2"));
}
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/** spring上下文的工具类 */
@Component
public class SpringContextUtil implements ApplicationContextAware {
/** 获取应用程序上下文对象 获取IoC容器内部的对象的时候,要结合上下文对象获取 */
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
/** 调用spring上下文,获取容器内对应的类型的对象 */
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
}
MessageDao messageDao = SpringContextUtil.getBean(MessageDao.class);